计算机里小数如何保存的

引言

今天没事的时候突然想起来一个经典问题,计算机里小数如何保存的

1
2
3
4
float b = 0.70000000f;
float c = 0.69999999f;
System.out.println(1-0.9);
System.out.println(b==c);

结果为

0.09999999999999998
true

这些现象就和计算机如何保存小数的密不可分,哈哈😂😂,
首先是十进制小数如何转换为二进制

十进制小数转换成二进制小数采用”乘2取整,顺序排列”法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
如:0.625=(0.101)B

0.625*2=1.25======取出整数部分1
0.25*2=0.5========取出整数部分0
0.5*2=1==========取出整数部分1
再如:0.7=(0.1 0110 0110...)B

0.7*2=1.4========取出整数部分1
0.4*2=0.8========取出整数部分0
0.8*2=1.6========取出整数部分1
0.6*2=1.2========取出整数部分1
0.2*2=0.4========取出整数部分0
0.4*2=0.8========取出整数部分0
0.8*2=1.6========取出整数部分1
0.6*2=1.2========取出整数部分1
0.2*2=0.4========取出整数部分0

就像十进制不能表示 1/3 这样,1/10 二进制也不能完美表示,
再精度范围外就会有数据丢失,所以1 - 0.9 得到的确实上面的数据

再来看看float存储方式

首先我们知道常用科学计数法是将所有的数字转换成(±)a.b x 1 0 c 10^c10
c
的形式,其中a的范围是1到9共9个整数,b是小数点后的所有数字,c是10的指数。而计算机中存储的都是二进制数据,所以float存储的数字都要先转化成(±)a.b x 2 c 2^c2
c
,由于二进制中最大的数字就是1,所以表示法可以写成(±)1.b x 2 c 2^c2
c
的形式,float要想存储小数就只需要存储(±),b和c就可以了。

float的存储正是将4字节32位划分为了3部分来分别存储正负号,小数部分和指数部分的:

Sign(1位):用来表示浮点数是正数还是负数,0表示正数,1表示负数。
Exponent(8位):指数部分。即上文提到数字c,但是这里不是直接存储c,为了同时表示正负指数以及他们的大小顺序,这里实际存储的是c+127。
Mantissa(23位):尾数部分。


计算机里小数如何保存的
http://xxpain.github.io/2021/09/10/float/
作者
无情小肥羊
发布于
2021年9月10日
许可协议