IEEE754浮点数 向偶数舍入

时间:2024-03-29 15:45:28

概念介绍

我们大家都知道,浮点数的标准是IEEE754。关于IEEE754格式这里不讲了,主要是要讲一下它的默认舍入方式。
因为表示方法限制了浮点数的范围和精度,所以使用浮点数只能近似地表示实数运算。而此时就不得不考虑舍入的问题了。舍入的原则是找到最接近的匹配值。
为此,IEEE754定义了四种不同的舍入方式:

  • 向偶数舍入
  • 向零舍入
  • 向下舍入
  • 向上舍入
    IEEE754默认采用向偶数舍入,用来找到最接近的匹配近似值。而其他三种方式则用于计算上下界。

下表是按照四种不同的方式保留整数后的舍入结果:
IEEE754浮点数 向偶数舍入

对于上表,除了向偶数舍入之外,大家应该都很熟悉了。会不会有人产生疑问:1.40向偶数舍入的结果竟然是一个奇数。哈哈,如果你有这个疑问,那表明你还没有搞懂什么是向偶数舍入。

向偶数舍入

所谓向偶数舍入(round-to-even),其真实的意思是向最接近的值舍入(round-to-nearest)。用通俗的话讲就是四舍六入五成双,或者四舍六入五凑偶。当然这句通俗的口诀是针对十进制来说的。
向偶数舍入只有两条规则:

  1. 如果最接近的值唯一,则直接向最接近的值舍入;
  2. 如果是处在“中间值”,那么要看保留位(Guard bit)是否是偶数,如果是偶数则直接舍去后面的数不进位,如果是奇数则进位后再舍去后面的数。

只要理解了上面两条规则,那么就完全掌握了向偶数舍入。为了详细解读这两条规则,下面将分别用十进制和二进制来举例说明。

保留位(Guard bit)、近似位(Round bit)和粘滞位(Sticky bit)

我们以十进制数来举例。如果我们想保留两位小数,即留下十分位和百分位上的数。那么保留位(Guard bit)就是结果的最低位,即百分位;近似位(Round bit)就是第一个被舍掉的位,即千分位;而千分位之后的所有位(包括万分位、十万分位等等)或起来构成粘滞位(Sticky bit)。

同理,对于二进制,如果我们想要保留两位小数,那么小数点右边第二位就是保留位(Guard bit),小数点右边第三位就是近似位(Round bit),小数点右边第四位开始一直向右的所有小数位或起来构成粘滞位(Sticky bit)。
用CMU的课件也许更容易理解一点。
IEEE754浮点数 向偶数舍入

中间值

在进行举例说明之前,我们有必要引入一个中间值的概念。这对于理解 “向偶数舍入” 至关重要。对于十进制来说,如果要保留一位小数,即百分位和百分位之后的小数都会被近似掉,那么此时中间值就是xxx.x5000…(5之后全零)。
也就是说,求中间值的方法如下:

  1. 保留位(Guard bit)和左边的数字保持不变;
  2. 近似位(Round bit)改写为N/2(N为进制数,十进制就是10,二进制就是2)
  3. 粘滞位(Sticky bit)全部写零
原始值(十进制) 中间值 (保留一位小数) 中间值 (保留两位小数)
1.334 1.350 1.335
1.622 1.650 1.625
1.744 1.750 1.745
1.835 1.850 1.835
1.668 1.650 1.665
1.774 1.750 1.775
1.488 1.450 1.485
原始值(二进制) 中间值 (保留一位小数) 中间值 (保留两位小数)
1.101 1.110 1.101
101.111 101.110 101.111
11.001 11.010 11.001
1.010 1.010 1.011
1.100 1.110 1.101

向偶数舍入 十进制举例

对于以下十进制的数值,我们采用向偶数舍入的方式,保留精确度到十分位,即保留一位小数。

  1. 请看第一组例子:

    原始值 中间值 近似值 (向偶数舍入)
    1.36 1.35 1.4
    1.751 1.75 1.8
    1.852 1.85 1.9
    1.77 1.75 1.8
    1.45001 1.45 1.5

    可以看到,上述这些原始值都比中间值要大,也就是“四舍六入五成双”中的“六入”。所以都向十分位进一,从而使得损失的精度最小。

  2. 请看第二组例子:

    原始值 中间值 近似值 (向偶数舍入)
    1.33 1.35 1.3
    1.74 1.75 1.7
    1.82 1.85 1.8
    1.71 1.75 1.7
    1.43 1.45 1.4

    可以看到,上述这些原始值都比中间值要小,也就是“四舍六入五成双”中的“四舍”。所以直接舍弃,不进位,从而使得损失的精度最小。

  3. 请看第三组例子:

    原始值 中间值 近似值 (向偶数舍入)
    1.35 1.35 1.4
    1.75 1.75 1.8
    1.85 1.85 1.8
    1.25 1.25 1.2
    1.45 1.45 1.4

    可以看到,上述这些原始值和中间值相等,也就是“四舍六入五成双”中的“五成双”。对于这些和中间值完全相等的原始值,我们考察保留位(Guard bit),如果保留位是偶数,则直接舍弃近似位(Round bit)和粘滞位(Sticky bit);如果保留位是奇数,则先向保留位进一,之后舍弃近似位(Round bit)和粘滞位(Sticky bit)。这样,结果中的保留位就是偶数了。这就是向偶数舍入 名字的由来。

向偶数舍入 二进制举例

对于以下二进制的数值,我们采用向偶数舍入的方式,保留一位小数。

  1. 请看第一组例子:

    原始值(二进制) 中间值 近似值 (向偶数舍入)
    1.111 1.11 10.0
    1.0101 1.01 1.1
    1.0111 1.01 1.1

    可以看到,上述这些原始值都比中间值要大,也就是“四舍六入五成双”中的“六入”。所以都向小数点右边第1位进一,从而使得损失的精度最小。

  2. 请看第二组例子:

    原始值(二进制) 中间值 近似值 (向偶数舍入)
    1.001 1.01 1.0
    1.10 1.11 1.1

    可以看到,上述这些原始值都比中间值要小,也就是“四舍六入五成双”中的“四舍”。所以直接舍弃,不进位,从而使得损失的精度最小。

  3. 请看第三组例子:

    原始值(二进制) 中间值 近似值 (向偶数舍入)
    1.110 1.11 10.0
    1.010 1.01 1.0

    可以看到,上述这些原始值和中间值相等,也就是“四舍六入五成双”中的“五成双”。对于这些和中间值完全相等的原始值,我们考察保留位(Guard bit),如果保留位是偶数,则直接舍弃近似位(Round bit)和粘滞位(Sticky bit);如果保留位是奇数,则先向保留位进一,之后舍弃近似位(Round bit)和粘滞位(Sticky bit)。这样,结果中的保留位就是偶数了。这就是向偶数舍入 名字的由来。

怎么样?现在彻底搞懂什么是向偶数舍入了吧。