浮点数内存存储格式

对于浮点数的存储格式一直很头疼

浮点数大部分都是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…