zl程序教程

您现在的位置是:首页 >  其它

当前栏目

浮点数零的格式定义,及其引发的潜在问题

格式 定义 及其 引发 浮点数 潜在 问题
2023-09-27 14:20:16 时间

1. 浮点数的定义

先说说浮点数的表示方法。任意二进制数N可以写成 N = ( − 1 ) s × 2 e × M N = (-1)^s\times2^e\times M N=(1)s×2e×M 的形式,其中 s是符号位,e是指数,M 称为浮点数的尾数,是一个纯小数。参照 IEEE R32.24 标准,看看 float32 的格式:
在这里插入图片描述

下面我们来看一个实际例子, 8.25 8.25 8.25 用十进制表示是 82.5 × 1 0 − 1 82.5 \times 10^{-1} 82.5×101, 那么用二进制表示是多少呢?

8.25 → 1000.01 × 2 0 → 1.00001 × 2 3 (1) \tag1 8.25 \to 1000.01\times 2^0 \to 1.00001 \times 2^3 8.251000.01×201.00001×23(1)

那么好啊,既然所有的二进制都可以表示成1.xxx * 2^xxx,那么小数点前面的肯定都是1了所以在存储到内存的时候默认都是1.xxx就好了,也没必要在内存中存储1这个bit了所以23bit的尾数部分,可以表示的精度却变成了24bit,道理就是在这里。

因此,32 位浮点数的实际表达形式变成了如下形式:
N = ( − 1 ) s × 2 e × ( 1 + M ) (2) \tag2 N=(-1)^s \times 2^e \times (1 + M) N=(1)s×2e×(1+M)(2)

对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127 ~ 128了,所以指数部分的存储采用移位存储,存储的数据为原数据+127,下面就看看8.25在内存中真正的存储方式。

这样的话我们得到 8.25 的 float32 表示方法:

符号位 = 0
阶码 = 127 + 3 = 130
尾数 = 00001000....

2. 浮点数零

按照上面的定义,当 s = 0 , e = 0 , M = 0 s=0,e=0,M=0 s=0,e=0,M=0 时,实际上表示的数值应该是
N = ( − 1 ) 0 × 2 − 127 × ( 1 + 0 ) = 2 − 127 N=(-1)^0 \times 2^{-127} \times (1 + 0) = 2^{-127} N=(1)0×2127×(1+0)=2127
于是,我们发现,按照前面的定义,数字 0 是无法表示的。所以 IEEE R32.24 标准强行规定, s = 0 , e = 0 , M = 0 s=0,e=0,M=0 s=0,e=0,M=0 时, N = 0 N=0 N=0

3. 浮点数在零附近的分布

我们只看正数吧!从数字 0 开始,从小到大列举最小的五个浮点数。
0 ( − 1 ) 0 × 2 − 127 × ( 1 + 2 − 23 ) = 2 − 127 + 2 − 150 ( − 1 ) 0 × 2 − 127 × ( 1 + 2 − 22 ) = 2 − 127 + 2 × 2 − 150 ( − 1 ) 0 × 2 − 127 × ( 1 + ( 2 − 23 + 2 − 22 ) ) = 2 − 127 + 3 × 2 − 150 ( − 1 ) 0 × 2 − 127 × ( 1 + 2 − 21 ) = 2 − 127 + 4 × 2 − 150 0\\ (-1)^0 \times 2^{-127}\times (1+2^{-23}) = 2^{-127}+2^{-150}\\ (-1)^0 \times 2^{-127}\times (1+2^{-22}) = 2^{-127}+2\times 2^{-150}\\ (-1)^0 \times 2^{-127}\times (1+(2^{-23} + 2^{-22})) = 2^{-127}+3\times2^{-150}\\ (-1)^0 \times 2^{-127}\times (1+2^{-21}) = 2^{-127}+4\times2^{-150}\\ 0(1)0×2127×(1+223)=2127+2150(1)0×2127×(1+222=2127+2×2150(1)0×2127×1+(223+222))=2127+3×2150(1)0×2127×1+221)=2127+4×2150

0 2 − 127 + 1 × 2 − 150 2 − 127 + 2 × 2 − 150 2 − 127 + 3 × 2 − 150 2 − 127 + 4 × 2 − 150 2 − 127 + 5 × 2 − 150 0\\ 2^{-127}+1\times2^{-150}\\ 2^{-127}+2\times2^{-150}\\ 2^{-127}+3\times2^{-150}\\ 2^{-127}+4\times2^{-150}\\ 2^{-127}+5\times2^{-150}\\ 02127+1×21502127+2×21502127+3×21502127+4×21502127+5×2150

请注意,0 与其后面的最小数据增量是 2 − 127 2^{-127} 2127,而后续的其他数据的增量是 2 − 150 2^{-150} 2150。也就是说,数字在渐渐减少到 0 的过程中突然降到了 0。 为了减少 0 与最小数字和最小数字与次小数字之间步 长的突然下跌,subnormal 规定:当指数位全 0 的时候,指数表示为 -126 而不是 -127( 和指数为最低 位为 1 一致)。 然而公式改成 ( − 1 ) s × M × 2 e (-1)^s \times M \times 2^e (1)s×M×2e, M 不再 +1, 这样最小的数字就变成 2 − 23 × 2 − 126 2^{- 23} \times 2^{- 126} 223×2126, 次小的数字变成 2 − 22 × 2 − 126 2^{- 22} \times 2^{-126} 222×2126, 每两个相邻 subnormal 数字 之差都是 2 − 23 × 2 − 126 2^{-23} \times 2^{-126} 223×2126, 避免 了 突然 降到 0。