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