浮点数内存存储格式
对于浮点数的存储格式一直很头疼
浮点数大部分都是IEEE标准存储
这个标准根本不能精确表示浮点数。。。只知道近似舍入。。。
来看 0.1
0.1根本不能用有限的二进制表示
先说十进制小数如何转换为二进制, 方法是乘2 取整,用余下的小数继续乘2取整
0.1X2 = 0.2 整数为0 取0
0.2X2=0.4 整数为0 取0
0.4x2=0.8 整数为0 取0
0.8x2=1.6 整数为1 取1
0.6X2=1.2 整数为1 取1
0.2X2=0.4 整数为0 取0 (这里可以看到小数部分又成了0.4 所以下面无限循环了。。。)
所以0.1的二进制表现为 . 0[0011] 方括号无限循环
所以你看0.1~0.9 只有0.5才可以精确表示,9个浮点数只有一个才能精确表示, 表示不能理解这个IEEE标准为什么好.(可能和CPU的硬件结构有关系吧)
0.5x2=1 取1 小数归0
0.5就是二进制.1 也就是1x2-1次方
关于十进制小数转换为二进制小数
假设一十进制小数B化为了二进制小数0.ab的形式,同样按权展开,得
B=a(2-1)+b(2-2)
因为小数部分的位权是负次幂,所以我们只能乘2,得
2B=a+b(2-1)
注意a变成了整数部分,我们取整数正好是取到了a,剩下的小数部分也如此。 A b要么是0 要么是1
所以我们上面的给小数乘2取整数部分 整数就是a
其实不管是十进制转二进制还是八进制、十六进制,原理都是一样的,即,连除(整数)取逆序或者连乘(小数)取顺序
再回头看我们IEEE 754浮点数的存储方式
根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:
V = (-1)^s×M×2^E
(1)(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
(2)M表示有效数字,当小数为规格化值时M大于等于1,小于2。 这样可以多保留一个精度, 例如二进制小数点后面是6位100001, 我们将第一位1隐藏,只用00001这5位,但是实际确可以表示6位浮点精度。。。 因为小数点左边还有一个1.。。。也就是用5bits 就可以表示6bits的小数。。。
(3)2^E表示指数位。
举例来说,十进制的5.0,写成二进制是101.0,相当于1.01×2^2。那么,按照上面V的格式,可以得出s=0,M=1.01(只存放01就可以),E=2。
十进制的-5.0,写成二进制是-101.0,相当于-1.01×2^2。那么,s=1,M=1.01,E=2。
根据exponent的值又分为下面几种情况
(1)exponent位不全为0或不全为1。 这叫做规格化值。。。 这时E=e-Bias, e为exponent的值,它是无符号类型。 Bias=2^(k-1)-1, k 为exponent的位数. 计算规格化时M必须为1+f… 多获取一位浮点精度. 也就是M总是>=1的
(2)exponent位全为0。这叫做非规格化值(E!= -1023 or E!=-126)。这时,浮点数的指数E等于1-Bias, Bias=2^(k-1)-1,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。 为什么规格化和非规格化的E取值方式不同, 这提供了一种平滑过渡,保证最大非规格化小数到最小规格化小数的分子总是相差1.。。 假设8位表示小数,1位符号位, 4位指数位,3位表示小数。 最大非规格化数为0 0000 111 = 7/512 最小规格化小数为0 0001 000 = 8/512 分子相差1
(3)exponent位全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
调式试一哈
double d = -10.0;
它在内存中存储为 如下,
注意VS里小端存储。。。 我们上面的图可以看到第一位是高位的。。。按照存储格式调整
d按照IEEE格式存储为如下二进制
1100(c) 0000(0) 0010(2) 0100(4) 00……
我们从二进制数推十进制
符号位S=1 所以为负数
由于是double类型, k = 11, bias=1023, exponent位不全为0属于规格化值, e为11位 100 0000 0010 = 0x402=1026. E=e-bias=1026-1023=3
M为0100 00….. 只看最后一个1, 因为M表示的是小数点后面存放的数字0.01 = 0.010000…. 也就是小数点后面的二进制数为01, 因为它是规格化值,所以M不要忘了+1, 小数点后面的01 = 0x2^-1+1x2^-2=1/4 , M = 1/4+1 = 5/4
套公式 V = (-1)^s×M×2^E
V=-1X5/4x2^3=-10
再次手推从10进制转换2进制
-10 的二进制为- 1010 注意别整补码。。
-1010 可以写成 - 1.01x2^3 (为什么是1.01 因为这里是规格化值, 所以M肯定是>=1)
E就是3, M为1.01 S为1
套公式V= -1x2^3x(1+1x2^-2)=-10…