前言
float数据是如何存储的,很多时候我不必关心过多的细节,但是有时候又很重要,了解一些计算机的基础知识,也是趣味无穷。
float数据的存储结构
float占用4个字节Byte,一共32bit。
计算机中只有“0”和“1”,那么如何用0”和“1”表示浮点呢。
IEEE标准中,将32bit的内存分为3个部分。
- 0~22bit,长度为23个bit,用
M
表示(Mantissa
,小数部分) - 23~30bit,长度为8个bit,用
E
表示(Exponent
,指数部分) - 31bit,最高位,只有1个bit,用
S
表示(Sign
,符号)
那么浮点数的换算公式如下,就是科学计数法的表示方式。
D
=
S
∗
(
1
+
M
)
∗
2
(
E
−
127
)
D=S*(1+M)*2^{(E-127)}
D=S∗(1+M)∗2(E−127)-------(1)
S
很好理解,就是正号+
或者符号-
。E
也很好理解,就是8个bit的二进制数对应的无符号整数,比如00000011b
表示0x03=3
,10100110b
表示0xA6=166
.M
理解稍难一些,因为涉及到二进制小数。假设在22bit的前面有一个小数点,那么需要把小数点后面的二进数转换为小数。比如 0.101 b = 1 ∗ 2 − 1 + 0 ∗ 2 − 2 + 1 ∗ 2 − 3 = 1 / 2 + 0 + 1 / 8 = 0.625 0.101b=1*2^{-1}+0*2^{-2}+1*2^{-3}=1/2+0+1/8=0.625 0.101b=1∗2−1+0∗2−2+1∗2−3=1/2+0+1/8=0.625
二进制转float
可以计算S、E、M
后,就可以计算对应的浮点数据。
直接举例说明吧,下图中,S = 0,E = 127, M = 0.625,带入公式(1)中:
D
=
(
+
1
)
∗
(
1
+
0.625
)
∗
2
(
127
−
127
)
=
1.625
D=(+1)*(1+0.625)*2^{(127-127)}=1.625
D=(+1)∗(1+0.625)∗2(127−127)=1.625
再来一个例子,下图中,S=-1, E=129,E=0.625,带入公式(1)中:
D
=
(
−
1
)
∗
(
1
+
0.625
)
∗
2
(
129
−
127
)
=
1.625
∗
4
=
6.5
D=(-1)*(1+0.625)*2^{(129-127)}=1.625*4=6.5
D=(−1)∗(1+0.625)∗2(129−127)=1.625∗4=6.5
不管其它任何的数据,都可以按照上述方法计算,如果还不会,再看一遍。
float转二进制
float转二进制,就是上述计算逆运算,注意到公式(1)中M要加上1了吗?
对公式(1)进行变形,M
写左边。因为
S
=
1
/
S
S=1/S
S=1/S,所以有
M
=
S
∗
D
2
(
E
−
127
)
−
1
M=\frac{S*D}{2^{(E-127)}}-1
M=2(E−127)S∗D−1 --------(2)
这个公式中,除了符号位S
外,仅仅只有D
是已知的,如何求另外2个未知数呢?
这里要遵循2个原则
- 先确定
E
,再确定M; - 确定
E
的方法是:让 D 2 ( E − 127 ) \frac{D}{2^{(E-127)}} 2(E−127)D恰好是1.xxxx
的形式,也就是这个数据的整数部分**必须是1,不能是0,也不能是2,或者其他。**E确定下来后,M也可以计算出来了。
还是举例说明,把13.25进行转换。
- 首先13.25的整数部分不是1,需要进行换算,需要除8,也就是 2 3 = 2 E − 127 2^{3}=2^{E-127} 23=2E−127,所以E=130=0x82
- 13.25/8=1.65625=1+M,所以M=0.65625=0.10101b
所以有S=1,E=130,M=0.10101b,如下图所示。
再来一个例子,把-0.20703125进行转换,S=-1。
- 首先0.20703125的整数部分不是1,需要进行换算,需要乘8,也就是除1/8,也就是 2 − 3 = 2 E − 127 2^{-3}=2^{E-127} 2−3=2E−127,所以E=124=0x7C
- 0.20703125*8=1.65625=1+M,所以M=0.65625=0.10101b
所以有S=-1,E=124,M=0.10101b,如下图所示。
上述是关于float的介绍,double数据的转换就依葫芦画瓢吧,这里就不啰嗦了。
参考链接
float和二进制换算的计算器
https://www.h-schmidt.net/FloatConverter/IEEE754.html
扩展链接
FLT_EPFILION定义以及原理
https://frama-c.com/2013/05/09/Definition-of-FLT_EPSILON.html