02计算机组成原理-浮点数的加减运算
前言
首先来看十进制的浮点数的加减:

不能将0.123和0.456直接相加,因为阶数不一样,要把阶数调整为相同(往大的调整)之后再相加。结果的尾数为两个尾数之和,阶数为调整之后的阶数。
所以,浮点数加减法运算其实很简单,总共就5步:
对阶、尾数运算、规格化、舍入、溢出判断。
x+(-)y=z为例,基于IEEE754标准 32位短浮点数
1.对阶
1.对阶:使x和y的阶码相等,以使尾数可以相加减。
原则:小阶向大阶看齐,阶小的那个数的尾数右移(算术移位),右移的位数等于两个阶(指数)的差的绝对值。
大多数机器采用IEEE754标准来表示浮点数,阶数为移码表示因此,对阶时需要进行移码减法运算 ,并且尾数右移时按原码小数方式右移,符号位不参加移位 ,数值位要将隐含的一位1右移到小数部分,空出位补0 。(例如1.0110移完后应为0.1011)为了保证运算的精度,尾数右移时,低位移出的位不要丢掉,应保留并参加尾数部分的运算。这是为了保证运算的精度
类似于1.523+1.266要求计算出来的结果保留两位小数,我们算的时候是用1.523+1.266计算出的结果后再保留两位小数,而不是直接1.52+1.26,后者丢失了精度。
移码减法运算。假设x和y的阶码分别为Ex和Ey,对应的移码分别为[Ex]移,[Ey]移
Ex\]移=Ex+2^n-1^-1 \[Ey\]移=Ey+2^n-1^-1 补码:X=(x+2^n^)mod 2^n^ \[Ex\]移-\[Ey\]移=\[Ex\]移+\[\[Ey\]移\]补=\[Ex\]移+2^n^-\[Ey\]移(mod 2^n^) 带入后算的(Ex-Ey)+2^n^(mod 2^n^)=\[Ex-Ey\]补 故\[Ex\]移-\[Ey\]移=\[Ex-Ey\]补,同理\[Ex\]移+\[Ey\]移=\[Ex+Ey\]补(前提偏置值是2^n-1^) tips:自己手算时直接用真值算即可 ## 2.尾数加减 2.尾数加减: 对阶后两个浮点数的指数相等,可以进行对阶后的尾数相加减。 因为IEEE754采用定点原码小数表示尾数,所以,尾数加减实际上是**定点原码小数的加减运算(与定点加减法一样)。** 因为IEEE754浮点数尾数中有一个隐藏位,所以,在进行尾数加减时,必须把**隐藏位还原到尾数部分** 。运算过程中,在尾数右移时保留的**附加位也要参加运算**。因此,在用定点原码小数进行尾数加减运算时,在操作数的高位部分和低位部分都需要进行相应的调整。 例如0110,1101这两个尾数格式,算的时候应该是1.0110加上1.1101,如果对阶的时候设计到把0110移动两位成010110,最后保留的10也要参与运算,0.010110加上1.1101。**注意隐藏位保存的时候隐藏了,但不管是对阶的时候还是运算的时候得还原进去一起运算** **进行加减运算后的尾数不一定是规格化的**,因此,浮点数的加、减运算需要进一步进行规格化处理。 ## 3.尾数规格化 3.尾数规格化:左规 右规 保证最高有效位为1 右规:尾数右移一位,阶码加1。尾数右移时,最高位1被移到小数点前一位作为隐藏位,最后一位移出时,要考虑舍入。阶码加1时,直接在末位加1。例如1b.bbb---\>1.bbbb e+1 左规:数值位逐次左移,阶码逐次减1,直到将第一位1(隐藏位)移到小数点左边。 0.001bb---\>1.bb e-1-1-1 ## 4.尾数的舍入处理 4.尾数的舍入处理:在对阶和尾数右规时,可能会对尾数进行右移,为保证运算精度,一般将低位移出的位保留下来,参加中间过程的运算,最后再将运算结果进行舍入,还原表示成IEEE 754格式。 (1)保留多少附加位才能保证运算的精度? IEEE754标准规定,所有浮点数运算的**中间结果** 右边都必须**至少额外保留两位附加位**。1数符 8阶码 23尾数--(两位附加位) 这两位附加位中,紧跟在浮点数尾数右边那一位为保护位或警戒位( guard) ,用以保护尾数右移的位;紧跟保护位右边的是舍入位( round) ,左规时可以根据其值进行舍入。在IEEE 754标准中,为了更进一步提高计算精度,在保护位和舍入位后面还引入了额外的一个数位,称为粘位(sticky),只要舍入位的右边有任何非0数字,粘位就被置1;否则,粘位被置0。 (2)IEEE754标准的舍入方法: * 0舍1入。 * 朝十∞方向舍入。总是取右边最近可表示数,也称为正向舍入或朝上舍入。例如1.01舍入为1.1 * 朝一∞方向舍入。总是取左边最近可表示数,也称为负向舍入或朝下舍入。如1.01舍入为1.00 * 朝0方向舍入。直接截取所需位数,丢弃后面所有位,也称为截取、截断或恒舍法。这种舍入处理最简单。对正数或负数来说,都是取更靠近原点的那个可表示数,是趋向原点的舍入,因此,又称为趋向零舍入。 ## 5.溢出判断 5.溢出判断: 在进行尾数规格化和尾数舍入时,可能会对结果的阶码执行加、减运算。因此,必须考虑结果的**指数溢出** 问题: 若一个正指数超过了最大允许值(127或1023),则发生指数上溢,机器产生异常,也有的机器把结果置为+∞(数符为0时)或-∞(数符为1时)后,继续执行下去。 若一个负指数超过了最小允许值(-149或-1074),则发生指数下溢,此时,一般把结果置为+0(数符为0时)或-0(数符为1时),也有的机器引起异常。 溢出判断实际上是在上述尾数规格化和尾数舍入过程中进行的,只要涉及阶码求和/差,就可以在阶码运算部件中直接用溢出判断电路来实现。涉及阶码求和/差的情况有以下情况: (1)右规和尾数舍入。一个数值很大的尾数舍入时,可能因为末尾加1而发生尾数溢出,此时,可以通过右规来调整尾数和阶。 右规时阶加1,导致阶增大,因此需要判断是否发生了指数上溢。只有当调整前的阶码为1111110,加1后,才会变成1111111而发生上溢;如果右规前阶码已经是1111111,则右规后变为0000000,因而会造成判断出错。所以,**右规前应先判断阶码是否为全1,若是,则不需右规,直接置结果为指数上溢;否则,阶码加1,然后判断阶码是否为全1来确定是否指数上溢。** (2)左规。左规时数值位逐次左移,阶码逐次减1,所以左规使阶码减小,故需判断是否发生指数下溢。 其判断规则与指数上溢类似,**首先判断阶码是否为全0,若是,则直接置结果为指数下溢;否则,阶码减1,然后判断阶码是否为全0来确定是否指数下溢。** 从浮点数加、减运算过程可以看出,浮点数的溢出并不以尾数溢出来判断,尾数溢出可以通过右规操作得到纠正。运算结果是否溢出主要看结果的指数是否发生了上溢,因此是由指数上溢来判断的。 --------------------------- 整个过程如下图:  接下来来看两个例子加深一下印象:用IEEE 754单精度浮点数加减运算计算0.5+(-0. 4375)。 x=0.5的二进制,0.10000...,规格化一下(1.0000...)=2^(-1)^,真值:-1+127=126得阶码0111 1110,由此得到0.5的IEEE 754单精度格式:0 01111110 000 0000 0000 0000 0000 0000 -y=0.4375=0.01110...=(1.1110)\*2^-2^,真值:-2+127=125,得阶码0111 1101,由此得到0.5的IEEE 754单精度格式:1 01111101 110 0000 0000 0000 0000 0000(存储时隐藏1) 1.对阶,明显0111 1110≠0111 1101,那就相减得到0000 0001,说明前者阶数大后者阶数小,且差值为1,说明我们需要把y的阶码+1,尾数位右移一位,My=1(1).1100...00(y的带符号尾数,这样写是为了展示给大家移位的时候不需要补符号位)Ey=0111 1110 My=1(0).1110...0 **00**(数值位要将隐含的一位1右移到小数部分,空出位补0。)加粗的后面两位是附加位。最后的那个0被移到附加位上了。 2.尾数相加 Mx=0(1).000...0 **00** My=1(0).1110...0 **00** 先看结果的符号位,谁的数值大结果就跟谁很显然Mx是1...,而My是0...所以Mx大,所以结果的符号位应该跟Mx,即0即正数,减完之后的数值是1.000...-0.11100...=0.0010...**00**,尾数的阶是0111 1110 3.规格化 小数点右移三位成1.000...00000 00,把附加位上的0左移出来了,阶码0111 1110-1-1-1=0111 1011 4.舍入 附加位上全0,去掉就完了,1.000...0000 5.判断溢出 整个计算过程中阶码都每全0或全1过,无溢出 结果,符号位为0,阶码0111 1011 尾数000 0000 0000 0000 0000 0000 即 0 0111 1011 000 0000 0000 0000 0000 0000(1.0\*2^-4^=0.0625)验证后正确 例2:设浮点数格式:阶码 尾数均用补码表述,补码含两位符号位。阶码占5位,尾数占7位,没有隐藏位。x=2^7^\*29/32,y=2^5^\*5/8,问x+y。 x=2^7^\*29/32----\>(直接把29的补码11101往左移动五位)Mx=00 11101 Ex=00 111 y=2^5^\*5/8---\>My=00 10100(因为是小数所以注意是右边补0),Ey=00 101 1.对阶,明显y的阶数小,故调整Ey=00 111,My右移2位:00 00101 2.尾数相加:00 11101+00 00101=01 00010(1.0001双符号位只管溢出,不管小数点,小数点在 符号位 和 数值位 之间,所以需要右规) 双符号位时: 00...... 或 11...... → 正常,不用规 01...... 或 10...... → 溢出,必须右规 1 位 3.规格化:右移一位,阶数+1=e+1= 00 111+1=01 000 而两位符号位,00代表正数,11代表负数,01和10都代表溢出,这里规格化后阶码数溢出了。故答案位溢出。 本来还有浮点数乘除的加减运算的,但是408大纲内没要求,我这就不写了。大概先写这些吧,今天的博客就先写到这,谢谢您的观看。