浮点数编码
记一个 32 比特长度的二进制数为:
b31b30b29…b2b1b0 根据 IEEE 754 标准,32-bit 长度的 float
由以下三个部分构成。
符号位 S :占 1 位 ,对应 b31。
指数位 E :占 8 位 ,对应 b30b29…b23。
分数位 N :占 23 位 ,对应 b22b21…b0。
二进制数 float
对应值的计算方法为:
val=(−1)b31×2(b30b29…b23)2−127×(1.b22b21…b0)2 转化到十进制下的计算公式为:
val=(−1)S×2E−127×(1+N) 其中各项的取值范围为:
S∈(1+N)={0,1},E∈{1,2,…,254}(1+i=1∑23b23−i2−i)⊂[1,2−2−23] 观察上图,给定一个示例数据 S=0 , E=124 ,N=2−2+2−3=0.375 ,则有:
val =(−1)0×2124−127×(1+0.375)=0.171875 现在我们可以回答最初的问题:float
的表示方式包含指数位,导致其取值范围远大于 int
。根据以上计算,float
可表示的最大正数为 2254−127×(2−2−23)≈3.4×1038 ,(2e−1−1=127)切换符号位便可得到最小负数。
尽管浮点数 float
扩展了取值范围,但其副作用是牺牲了精度。整数类型 int
将全部 32 比特用于表示数字,数字是均匀分布的;而由于指数位的存在,浮点数 float
的数值越大,相邻两个数字之间的差值就会趋向越大。
如下表所示,指数位 E=0 和 E=255 具有特殊含义,用于表示零、无穷大、NaN 等。
指数位 E
分数位 N = 0
分数位 N != 0
计算公式
(−1)S×2−126×(0.N)
1,2,…,254
(−1)S×2(E−127)×(1.N)
值得说明的是,次正规数显著提升了浮点数的精度。最小正正规数为 2−126 ,最小正次正规数为 2−126×2−23。双精度 double
也采用类似于 float
的表示方法,在此不做赘述。
Last updated