浮点数的运算
由于计算机存储空间位数的限制,使得计算机算术具有有限精度,而自然算术具有无限精度,因此在两者的转换之间必然存在转换精度。
一、 浮点数加减运算
例子:
(
0.5
)
10
(0.5)_{10}
(0.5)10和
(
−
0.4375
)
10
(-0.4375)_{10}
(−0.4375)10的和。
解:
- 首先,将十进制数转化为IEEE 754标准二进制,假设有效位数为4:
( 0.5 ) 10 = 1 2 = 1 × 2 − 1 = ( 1.000 ) 2 × 2 − 1 (0.5)_{10}=\frac{1}{2}=1\times2^{-1}=(1.000)_{2}\times2^{-1} (0.5)10=21=1×2−1=(1.000)2×2−1
( − 0.4375 ) 10 = 7 2 4 = 7 × 2 − 4 = ( − 111 ) 2 × 2 − 4 = ( − 1.110 ) 2 × 2 − 2 (-0.4375)_{10}=\frac{7}{2^{4}}=7\times2^{-4}=(-111)_{2}\times2^{-4}=(-1.110)_{2}\times2^{-2} (−0.4375)10=247=7×2−4=(−111)2×2−4=(−1.110)2×2−2 - 接下来,进行浮点数运算
[1] 对阶:选取指数较小的数进行对阶, ( − 1.110 [ 00 ] ) 2 × 2 − 2 = ( − 0.111 [ 00 ] ) 2 × 2 − 1 (-1.110[00])_{2}\times2^{-2}=(-0.111[00])_{2}\times2^{-1} (−1.110[00])2×2−2=(−0.111[00])2×2−1;
[2] 有效数相加: ( 1.000 [ 00 ] ) 2 × 2 − 1 + ( − 0.111 [ 00 ] ) 2 × 2 − 1 = ( 0.001 [ 00 ] ) 2 × 2 − 1 (1.000[00])_{2}\times2^{-1}+(-0.111[00])_{2}\times2^{-1}=(0.001[00])_{2}\times2^{-1} (1.000[00])2×2−1+(−0.111[00])2×2−1=(0.001[00])2×2−1;(原码的加减法)
[3] 规格化: ( 0.001 [ 00 ] ) 2 × 2 − 1 = ( 1.000 [ 00 ] ) 2 × 2 − 4 (0.001[00])_{2}\times2^{-1}=(1.000[00])_{2}\times2^{-4} (0.001[00])2×2−1=(1.000[00])2×2−4,阶码 − 126 ≥ − 4 ≤ 127 -126\ge -4\le127 −126≥−4≤127,故未溢出;
[4] 舍入:采用偶数舍入得到 ( 1.000 ) 2 × 2 − 4 (1.000)_{2}\times2^{-4} (1.000)2×2−4,且满足规格化要求。
注:对阶的过程中,有效数右移会使得尾数低位数据被抛弃,会出现丢失精度的情况,尤其是两数数值相差很大的数据,例如对于4位精度, 1.000 × 2 2 1.000\times2^{2} 1.000×22和 1.000 × 2 − 2 1.000\times2^{-2} 1.000×2−2相加时, 1.000 × 2 − 2 1.000\times2^{-2} 1.000×2−2右移4位,使得1被抛弃,最终结果依然为 1.000 × 2 2 1.000\times2^{2} 1.000×22,这个也称为大数吃小数。可以通过kahan Summation算法来解决。
二、浮点数乘除法运算
例子:
(
0.5
)
10
(0.5)_{10}
(0.5)10和
(
−
0.4375
)
10
(-0.4375)_{10}
(−0.4375)10的积
解:
- 首先,将十进制数转化为IEEE 754标准二进制,假设有效位数为4:
( 0.5 ) 10 = 1 2 = 1 × 2 − 1 = ( 1.000 ) 2 × 2 − 1 (0.5)_{10}=\frac{1}{2}=1\times2^{-1}=(1.000)_{2}\times2^{-1} (0.5)10=21=1×2−1=(1.000)2×2−1
( − 0.4375 ) 10 = 7 2 4 = 7 × 2 − 4 = ( − 111 ) 2 × 2 − 4 = ( − 1.110 ) 2 × 2 − 2 (-0.4375)_{10}=\frac{7}{2^{4}}=7\times2^{-4}=(-111)_{2}\times2^{-4}=(-1.110)_{2}\times2^{-2} (−0.4375)10=247=7×2−4=(−111)2×2−4=(−1.110)2×2−2 - 接下来,进行浮点数运算
[1] 阶码相加,并减去偏移量: ( − 1 + 127 ) + ( − 2 + 127 ) − 127 = 124 (-1+127)+(-2+127)-127=124 (−1+127)+(−2+127)−127=124,阶码 1 ≤ 124 ≤ 255 1\le 124\le255 1≤124≤255,故未溢出;
[2] 有效数的绝对值相乘: ( 1.000 [ 00 ] ) 2 × ( 1.110 [ 00 ] ) 2 = ( 1.110 [ 00 ] ) 2 (1.000[00])_{2}\times(1.110[00])_{2}=(1.110[00])_{2} (1.000[00])2×(1.110[00])2=(1.110[00])2;(原码的乘除法)
[3] 规格化: ( 1.110 [ 00 ] ) 2 × 2 − 3 (1.110[00])_{2}\times2^{-3} (1.110[00])2×2−3是规格数,阶码 1 ≤ ( − 3 + 127 ) ≤ 255 1\le(-3+127)\le255 1≤(−3+127)≤255,故未溢出;
[4] 舍入:偶数舍入得到 ( 1.110 ) 2 × 2 − 3 (1.110)_{2}\times2^{-3} (1.110)2×2−3,且满足规格化要求。
[5] 符号位判断:两数异号,结果为负数,即 ( − 1.110 ) 2 × 2 − 3 (-1.110)_{2}\times2^{-3} (−1.110)2×2−3
注:
- 阶码相加后为什么要减去偏移量?
− 1 -1 −1对应的阶码是 ( − 1 + 127 ) (-1+127) (−1+127), − 2 -2 −2对应的阶码是 ( − 2 + 127 ) (-2+127) (−2+127),它们的实际值之和为 ( − 1 ) + ( − 2 ) = − 3 (-1)+(-2)=-3 (−1)+(−2)=−3,阶码之和为 ( − 1 + 127 ) + ( − 2 + 127 ) (-1+127)+(-2+127) (−1+127)+(−2+127)显然阶码和与实际值之和不对应,应该要在阶码和的基础上减去127,即 ( − 1 + 127 ) + ( − 2 + 127 ) − 127 = − 3 + 127 (-1+127)+(-2+127)-127=-3+127 (−1+127)+(−2+127)−127=−3+127。除法的推导过程类似。- 上述运算过程中方括号内部的数代表附加位,即在原有尾数后再添加位数,使得进行舍入时能够保持更高的精度。对于IEEE 754标准,规定至少保留2位附加位,紧邻着尾数的称为保护位,接下来一位称为舍入位。
- 除法时也注意判断除数为0之类的特殊情况。
出现丢失精度的情况:
- 加减法:对阶、规格化、舍入
- 乘除法:规格化(乘法只有右规,除法只有左规)、舍入
注:左规时不会抛弃位数左端的1,而只会抛弃0,并将改变的权重体现在了阶码上,因此左规不会丢失精度,而右规则可能会丢数。
三、舍入方式
IEEE 754定义了4种不同的舍入方式。
- 偶数舍入:向最近的数舍入,当位于两数中间时,向偶数舍入,此方式为默认舍入方式;
- 向零舍入:在数轴上向靠近0的方向舍入;
- 向下舍入:在数轴上向负半轴方向舍入;
- 向上舍入:在数轴上向正半轴方向舍入;
示例:
舍入方式 | 1.40 | 1.60 | 1.50 | 2.50 | -1.50 |
---|---|---|---|---|---|
偶数舍入 | 1 | 2 | 2 | 2 | -2 |
向零舍入 | 1 | 1 | 1 | 2 | -1 |
向下舍入 | 1 | 1 | 1 | 2 | -2 |
向上舍入 | 2 | 2 | 2 | 3 | -1 |
注:为什么向偶数舍入?
当一个待舍入的数位于相邻两数正中间时,如果只采取向上或向下的舍入时,总体数据的统计平均值也会相应增大或减小,而采取向偶数或向奇数舍入时,从概率的角度而言可以避免这种统计偏差。
四、参考文献
[1]《深入理解计算机系统》第3版
[2]《计算机组成与设计-软件/硬件接口设计》第5版
[3]《数字逻辑与计算机组成》