二进制浮点数的规格化表示形式定义为 N = 2 E ⋅ M N=2^E·M N=2E⋅M其中 M M M称为尾数, E E E称为阶码
例如二进制浮点数11.011011的规格化表示形式为: 2 + 0010 × 0.11011011 2^{+0010}×0.11011011 2+0010×0.11011011该浮点数在计算机中存储为:
00100011011011
各个二进制位代表的含义为:
阶符E | 阶码E | 尾符M | 尾码M
00 010 00 11011011
现假设有两浮点数 X X X、 Y Y Y:
X : 2 + 010 × 0.11011011 X:2^{+010}×0.11011011 X:2+010×0.11011011 Y : 2 + 100 × − 0.10101100 Y:2^{+100}×-0.10101100 Y:2+100×−0.10101100
则 X X X、 Y Y Y在计算机中表示为:
阶符E | 阶码E | 尾符M | 尾码M
X 00 010 00 11011011
Y 00 100 11 01010100
要在计算机中实现加减法运算要执行5个步骤:
对阶的目的是为了使两个阶数不同的浮点数变换到为可以直接相加,例如在十进制中 1.2 × 1 0 2 1.2×10^2 1.2×102和 2.3 × 1 0 3 2.3×10^3 2.3×103的尾数是不能直接相加的,必须转换成相同的阶数才可以相加
1.2 × 1 0 2 + 2.3 × 1 0 3 ‾ 3.3 × 1 0 ? ⟹ 0.12 × 1 0 3 + 2.3 × 1 0 3 ‾ 2.42 × 1 0 3 \begin{aligned} & \quad 1.2 × 10^2 \\ & \underline{+\ 2.3 × 10^3}\\ & \quad 3.3 × 10^?\\ \end{aligned}\Longrightarrow \begin{aligned} & \quad 0.12 × 10^3 \\ & \underline{+\ 2.3 \ \ × 10^3}\\ & \quad 2.42 × 10^3\\ \end{aligned} 1.2×102+ 2.3×1033.3×10?⟹0.12×103+ 2.3 ×1032.42×103
保留两个浮点数中阶码较大的那一个浮点数的阶数,较小阶码的浮点数的阶数在之后需要对齐大阶,取大阶的公式为: E m a x = max ( E X , E Y ) E_{max} = \max(E_X,E_Y) Emax=max(EX,EY)之所以是取大阶而不是取小阶是因为,浮点数往小阶对其后,小数点会进入尾数之中,与上面举的例子不同,这种浮点数形式是无法在计算机中存储的。
取大阶举例,对 X X X、 Y Y Y取大阶:
E m a x = max ( E X , E Y ) = E Y E_{max} = \max(E_X,E_Y)=E_Y Emax=max(EX,EY)=EY
求出阶差后可以根据阶差对阶码小的浮点数的尾数进行调整,求阶差公式: Δ E = ∣ E X − E Y ∣ 补 \Delta E = |E_{X}-E_{Y}|_{补} ΔE=∣EX−EY∣补
求阶差举例,对 X X X、 Y Y Y求阶差:
Δ E = ∣ E X − E Y ∣ 补 = ∣ E X 补 − E Y 补 ∣ = ∣ E X 补 + ( − E Y ) 补 ∣ = ∣ 00010 + 11100 ∣ = ∣ 11110 ∣ = 2 \begin{aligned} \Delta E=& |E_{X}-E_{Y}|_{补}\\ =& |E_{X补}-E_{Y补}|\\ =& |E_{X补}+(-E_{Y})_{补}|\\ =& |00010 + 11100|\\ =& |11110|=2 \end{aligned} ΔE=====∣EX−EY∣补∣EX补−EY补∣∣EX补+(−EY)补∣∣00010+11100∣∣11110∣=2
若1.2求阶差中 Δ E ≠ 0 \Delta E \neq 0 ΔE=0,则执行对阶操作,将阶码值较小的浮点数尾数右移 Δ E \Delta E ΔE位,使得两个浮点数的阶码值相等。
由于进行了右移,对阶操作往往会损失阶码值较小的浮点数的一部分精度从而产生计算误差,若要减小计算误差,则要将右移过程中损失的尾数值保留下了以供后面3.2.2左规格化和4.2舍入步骤使用,这里不细说。
对阶举例,对 X X X、 Y Y Y对阶:
已知 X X X、 Y Y Y的大阶阶码 E m a x = E Y E_{max}=E_Y Emax=EY,阶差 Δ E = 2 \Delta E=2 ΔE=2。即 E X E_X EX位向 E Y E_Y EY对齐,且 M X M_X MX右移 Δ E \Delta E ΔE位:
00010 ‾ 00 11011011 ‾ ⟹ 00100 ‾ 00 00110110 ‾ \underline{00010}00\underline{11011011}\Longrightarrow\underline{00100}00\underline{00110110} 000100011011011⟹001000000110110对阶后的 X X X、 Y Y Y:
阶符E | 阶码E | 尾符M | 尾码M
X 00 100 00 00110110
Y 00 100 11 01010100
对阶前的 X X X、 Y Y Y:
阶符E | 阶码E | 尾符M | 尾码M
X 00 010 00 11011011
Y 00 100 11 01010100
对阶操作完成之后浮点数的尾数就可以进行运算了,公式可以表示为: M = [ ( M X ) ± ( M Y ) ] 补 M=[(M_X)\pm(M_Y)]_补 M=[(MX)±(MY)]补
尾数运算举例,对 X X X、 Y Y Y的尾数进行运算:
M = [ ( M X ) + ( M Y ) ] 补 = ( M X ) 补 + ( M Y ) 补 M=[(M_X)+(M_Y)]_补=(M_X)_补+(M_Y)_补 M=[(MX)+(MY)]补=(MX)补+(MY)补
00100 0000110110 ‾ + 00100 1101010100 ‾ ‾ 00100 1110001010 ‾ \begin{aligned} & \quad 00100\underline{0000110110} \\ & \underline{+\ 00100\underline{1101010100}}\\ & \quad 00100\underline{1110001010}\\ \end{aligned} 001000000110110+ 001001101010100001001110001010
双符号位的判断溢出方法:二进制数的符号一定为00(正)或11(负),运算后若符号位变为01则是正溢出,变为10则是负溢出,二进制数相加结果符号位溢出判断如下表所示:
正数 | 负数 | 正溢 | 负溢 |
---|---|---|---|
00 | 11 | 01 | 10 |
可以简记为,符号位异或的结果为0则溢出,为1则不溢出。
若尾数加减后的结果 M M M溢出则执行右规格化操作,即尾数右移一位且阶码加1,表示为 M ≫ 1 , E + 1 M\gg 1,E+1 M≫1,E+1
若尾数加减后的结果 M M M不溢出则执行左规格化操作,即尾数左移K位且阶码减K,表示为 M ≪ K , E − K M\ll K,E-K M≪K,E−K其中 K K K表示将尾数数值最高位变为与尾数符号位不同值需要执行左移的次数。注意此处的左移要包括1.3对阶时被移出低位的尾数值。
左规格化的目的是为了提高尾数的精度,例如, M = 001001110001010 M=001001110001010 M=001001110001010转为真值表示为 2 4 × − 0.01110110 2^4×-0.01110110 24×−0.01110110,由于在计算机中尾数的存储位数有限,这种表示方法就会造成精度的下降,改为 2 3 × − 0.11101100 2^3×-0.11101100 23×−0.11101100就可以多存一个位的数据
尾数运算举例,对 M M M的尾数进行左规格化:
尾数左移1位(括号中为对阶时被移出低位的尾数值): 1 11 ‾ 0001010 ( 11 ) ⟹ 1 10 ‾ 0010101 ( 1 ) 1\underline{11}0001010(11)\Longrightarrow 1\underline{10}0010101(1) 1110001010(11)⟹1100010101(1)阶码减1: 00100 − 00001 = 00011 00100-00001=00011 00100−00001=00011
如果在上一步执行的是右规格化,则要判断阶码是否上溢,若执行的是左规格化,则要判断阶码是否下溢。
判断方法与3.1一致,符号位异或的结果为0则溢出,为1则不溢出。右规格化若上溢则置上溢标志并且报运算结果溢出错误,左规格化若下溢则置机器零到5.4输出结果
若左右规格化的步骤执行后结果不溢出,则进行舍入处理。
在执行3.2.1右规格化和1.3对阶时,尾数低位上的数值会被移除掉使得浮点数精度下降。舍入就是用来弥补被移除掉的精度,当移除掉的低位数值最高位为1时,在规格化后的尾数末尾加1,若加1后使得尾数溢出,则需再执行一次右规格化。
舍入举例,对规格化后的 M M M的尾数进行舍入:
在1.3对阶时被移除掉的两个低位数是11,则移除掉的低位数值最高位为1,应在规格化后的尾数末尾加1,得到: M = M + 1 = 1100010101 + 000000001 = 1100010110 M=M+1=1100010101+000000001=1100010110 M=M+1=1100010101+000000001=1100010110
执行完舍入之后,要判断舍入之后的尾数是否溢出,判断方法与3.1一致,符号位异或的结果为0则溢出,为1则不溢出。若不溢出则输出结果。
若溢出则需要在执行一次右规格化,然后判断是否上溢,若上溢则置上溢标志并且报运算结果溢出错误,若不上溢则输出运算结果
最终结果可以用 X ± Y X\pm Y X±Y来表示,其值就是EM的真值 X ± Y = E 真 × M 真 X\pm Y=E_真×M_真 X±Y=E真×M真
结果举例,对规格化后的 M M M的尾数进行舍入:
M = 1100010110 ⟹ X + Y = E 真 × M 真 = 2 011 × − 0.11101010 M=1100010110\Longrightarrow X+Y=E_真×M_真=2^{011}×-0.11101010 M=1100010110⟹X+Y=E真×M真=2011×−0.11101010