IEEE 754 标准

浮点数是计算机科学中一种对于实数的近似数值表示法,由一个有效数字(尾数)加上幂数来表示,即二进制的科学计数法。IEEE 协会为了规范统一(方便CPU指令制造,各平台兼容等等)出台了 IEEE Standard for Floating-Point Arithmetic(IEEE-754)二进制浮点数算数标准,选用了浮点数作为储存和算数标准。 该标准描述了包括"浮点数的格式"、“一些特殊数值”、“浮点数的运算”、“舍入规则与例外情况” 等等内容。

IEEE 754 规定了5种表示浮点数的方式:

  • binary32(java中的float)
  • binary64(java中的double)
  • binary128
  • decimal64
  • decimal128

32位单精度浮点数内存模型

32位浮点数的内存被划分为3个部分:

  • sign: 符号位,0为正,1为负,占位1bit(第31索引位置)
  • exponent: 无符号整数,占位8bit,表示指数的值,此处范围为[0,256]。实际使用时会加上一个固定的偏移量-127,这样就表示负数,即可能的取值范围为[-127,128]
    • 实际上的取值范围为[-126,127],因为 −127(所有位是0)和 +128(所有位是1)的指数是为特殊数字保留的
  • fraction:精度值,占位23bit,存储有效数字24位(归一化的有效数字的最高位一定是1,于是将最高位的1隐式存储,这里默认不包含前导1。特殊数据除外,请参阅下面的指数编码)。

因此对于给定的32位二进制数(b0,b31b_{0},b_{31})有:

value=(1)b31×2E127×(1+i=123b23i2i)value = (-1)^{b_{31}} \times 2^{E-127} \times (1+ \sum_{i=1}^{23}b_{23-i}2^{-i})

E=i=07b23+i2+iE = \sum_{i=0}^{7}b_{23+i}2^{+i}

下面我们来看个例子:

可以使用上面的公式计算出单精度数的值为:

value=(1)0×2124127×(1+122)=0.15625value = (-1)^0 \times 2^{124-127} \times (1+1*2^{-2}) = 0.15625

指数编码

单精度二进制浮点指数使用偏移二进制数进行编码,零值的对应偏移量为127,即所有位是0表示−127,这在IEEE 754标准中也被称为指数偏差。为了获得由偏移二进制表示形式定义的真指数,必须从存储的指数中减去127的偏移量。

exponentfraction
000000000±0
00000000次正规数(1)sign×2126×0.fraction(-1)^{sign}\times2^{-126}\times0.fraction
[00000001,11111110]正规数(1)sign×2exponent127×1.fraction(-1)^{sign}\times2^{exponent-127}\times1.fraction
111111110±Infinity(无穷大)
11111111次正规数NAN(未定义或不可表示的值)

在正常的浮点值中,有效数(尾数)中没有前导零,会通过调整指数的方式来删除前导零。例如,0.0123的正规数表示形式是 1.23×1021.23\times10^{-2}。而次正规数则允许前导零的存在,即表示为 0.123×1010.123\times10^{-1}。可以发现在浮点数中,由于没有前导数1,只要fraction尽可能小,那么次正规数可以表示比正规数更接近0的数字。

NaN在计算机中表示not a number,可以解释为未定义或无法表示的值。例如,对于0/0在计算机中就由NaN表示。NaN 也可用于表示计算中的缺失值。

双精度内存模型

64位浮点数的内存被划分为3个部分:

  • sign: 符号位,0为正,1为负,占位1bit(第63索引位置)
  • exponent: 无符号整数,占位11bit,表示指数的值,此处范围为[0,2047]。实际使用时会加上一个固定的偏移量-1023,这样就表示负数,即可能的取值范围为[-1023,1024]
    • 实际上的取值范围为[-1022,1023],因为 −1023(所有位是0)和 +1024(所有位是1)的指数是为特殊数字保留的
  • fraction:精度值,占位52bit,存储有效数字53位(归一化的有效数字的最高位一定是1,于是将最高位的1隐式存储,这里默认不包含前导数1,特殊数据除外,请参阅指数编码)。

因此对于给定的64位二进制数(b0,b63b_{0},b_{63})有:

value=(1)b63×2E1023×(1+i=152b52i2i)value = (-1)^{b_{63}} \times 2^{E-1023} \times (1+ \sum_{i=1}^{52}b_{52-i}2^{-i})

E=i=011b52+i2+iE = \sum_{i=0}^{11}b_{52+i}2^{+i}

指数编码

双精度二进制浮点指数使用偏移二进制表示进行编码,零偏移为 1023。

exponentfraction
000000000000±0
00000000000次正规数(1)sign×21022×0.fraction(-1)^{sign}\times2^{-1022}\times0.fraction
[00000000001,11111111110]正规数(1)sign×2exponent1023×1.fraction(-1)^{sign}\times2^{exponent-1023}\times1.fraction
111111111110±Infinity(无穷大)
11111111111次正规数NAN(未定义或不可表示的值)

浮点数舍入规则

IEEE-754定义了五条舍入规则,前两个规则是舍入到最接近的值,其他的是有方向的四舍五入。

  • 舍入到最近,优选偶数:舍入到最近的值,如果数字落在了中间,那就选择最近的偶数。例如,11.5舍入到12,12.5舍入到12.
  • 舍入带最近,远离0:舍入到最近的值,如果数字落在了中间,那就选择离0的更远的数,较大值(对于正数)或较小值于(对于负数)。
  • 舍入到0: 定向舍入到0,也称为截断。
  • ++\infty 四舍五入: 向正无穷大方向舍入(也称为向上舍入或上限).
  • -\infty 四舍五入: 向负无穷大四舍五入(也称为向下舍入或下限).

参考