浮点数

浮点格式的数字是怎么表示的,以及舍入问题。

公式

计算机中只有 0 和 1,它表示小数的公式如下。

b=i==nm2i×bib = \sum_{i==-n}^m 2^i \times b_i

负次幂就可以表示小数点后面的值。所以可以看出来二进制小数只能近似表示一个数,可以通过增加二进制表示的长度来提高精度。

IEEE 浮点表示

IEEE 标准采用如下形式来表示一个数。

V=(1)s×M×2EV = \left(-1\right)^s \times M \times 2^E

  • 符号 s 决定正负号
  • 尾数 M 是一个二进制小数,范围一般是 [1, 2)
  • 阶码 E 的作用对浮点数加权

对于单精度浮点数来说。

位置大小名称
311符号
23-308阶码
0-2223尾数

对于双精度浮点数来说。

位置大小名称
631符号
52-6211阶码
0-5152尾数

规格化的值

exp 对应 E 表示的部分,frac 对应 M 表示的部分。当 exp 的位模式既不全为 0 或者 1 的时候,属于规格化的。

此时 E = e - Bias,其中 e 是无符号数,Bias 等于 2k112^{k-1}-1。由此产生指数的取值范围,单精度是 126+127-126 \sim +127,双精度是 1022+1023-1022 \sim +1023
小数字段 frac 用来解释小数值 f。其中 f 的范围是 [0, 1),二进制表示为 0.fn1f1f00_.f_{n-1}\cdots f_1f_0
M 则是隐含一个 1,所以 M 的二进制表示为 1.fn1f1f01_.f_{n-1}\cdots f_1f_0

非规格化的值

当阶码域全为 0 的时候,所表示的数是非格式化的形式。

此时 E = 1 - Bias,而尾数的值 M = f,也就是小数字段的值,不包含隐含的开头的 1。之所以 E 不等于 -Bias,为了后面最大非格式化数字和最小格式化数字之间的平滑转变。

非格式化可以用来表示数值 0。当阶码和小数域全是 0 的时候,就可以得到 -0 和 +0。

另外就是用来表示接近 0.0 的数,当 exp 全为 0 的时候,frac 不全为 0 的时候,数值是接近 0 的,并且间距是一样的。

特殊值

当 exp 全是 1 的时候,用来表示一些特殊值。

当 frac 全是 0 的时候,表示 \infty
当 frac 不全是 0 的时候,表示不是个数值 NaN。

舍入

浮点运算只能近似地表示实数运算。下面的舍入都是建立在最后一位是分界点 5 处。否则就是四舍五入了。

向上和向下舍入很容易理解,就是往小还是往大方向靠近舍入。
向偶数舍入,就是正好往偶数方向靠近。
向零舍入则是正数往下舍入,负数往上舍入。

偶数进位

关于向偶数进位,发现这篇文章[1]解释地很清楚。有效数字超出规定数位的多余数字是 1001,它大于超出规定最低位的一半(即 0.5),故最低位进 1。如果多余数字是 0111,它小于最低位的一半,则舍掉多余数字(截断尾数、截尾)即可。对于多余数字是 1000、正好是最低位一半的特殊情况,最低位为 0 则舍掉多余位,最低位为 1 则进位 1、使得最低位仍为 0(偶数)。

举例:要求保留小数点后 3 位。

对于 1.0011001,舍入处理后为 1.010(去掉多余的 4 位,加 0.001
对于 1.0010111,舍入处理后为 1.001(去掉多余的 4 位)
对于 1.0011000,舍入处理后为 1.010(去掉多余的 4 位,加 0.001,使得最低位为 0)

对于 1.1001001,舍入处理后为 1.101(去掉多余的 4 位,加 0.001
对于 1.1000111,舍入处理后为 1.100(去掉多余的 4 位)
对于 1.1001000 ,舍入处理后为 1.100(去掉多余的 4 位,不加,因为最低位已经为 0)

对于 1.01011,舍入处理后为 1.011(去掉多余的 2 位,加 0.001)
对于 1.01001,舍入处理后为 1.010(去掉多余的 2 位)
对于 1.01010,舍入处理后为 1.010(去掉多余的 2 位,不加)

对于 1.01111,舍入处理后为 1.100(去掉多余的 2 位,加0.001)
对于 1.01101,舍入处理后为 1.011(去掉多余的 2 位)
对于 1.01110,舍入处理后为 1.100(去掉多余的 2 位,加 0.001)

总结

  1. E 不全是 0 或者不全是 1 的时候,指数 E 的值需要减去偏置。M 需要加上隐藏的 1。
  2. E 全是 0 的时候,M 不需要加上隐藏的 1。
  3. E 全是 1 的时候,如果 M 全是 0,表示正负无穷大;如果全是 1 的时候,表示不是一个数,也就是 NaN

  1. 浮点数向偶数舍入的问题 ↩︎