定点除法运算

计算机中,除法运算和乘法运算一样,是非常常用的一种运算。同样,除法运算在计算机中的实现也分为符号部分和数值部分两部分。

(1)符号位。符号位的确定和乘法运算的规则一致,除法运算的符号位无法通过转换补码,加入到除法运算中,必须单独进行处理。根据除法运算的规则:被除数和除数之间,符号位相同则为正,符号位不同则为负。设被除数和除数分别为X和Y,Xf和Yf分别代表X和Y的符号位,除法运算结果为Z,Zf代表Z的符号位。如下表所示。

除法运算符号位结果真值表
Xf Yf Zf
0 0 0
0 1 1
1 0 1
1 1 0

根据真值表,可得除法运算符号位的逻辑表达式为:

Zf=Xf异或Yf

(2)恢复余数法实现数值部分除法。数值部分除法在计算机中的实现也是从除法运算的笔算演变过来的。我们不考虑符号位,以两个正数的除法为例,做出一个除法运算笔算例子的完整过程。

【例】设二进制小数X=0.1001,Y=0.1101,计算X/Y

X/Y的竖式如下:

                                     0.  1  0  1  1

0.1101          /  __________________

                    0.  1  0  0  1  0

                    0.  0  1  1  0  1

扫描二维码关注公众号,回复: 11329379 查看本文章

—————————————————

                    0.  0  0  1  0  1  0  0

                    0.  0  0  0  1  1  0  1

—————————————————

                    0.  0  0  0  0  1  1  1  0

                    0.  0  0  0  0  1  1  0  1

—————————————————

                    0.  0  0  0  0  0  0  0  1

结果为:X/Y的商为0.1011,余数为0.00000001

计算机中的定点数的除法运算,商的位数一般与被除数和除数的位数相等。观察运算过程发现,除法运算笔算每次都上商,都是通过心算比较余数和除数的大小关系,如果余数大于除数,上1,然后做减法得出新的余数,新的余数低位补0;如果余数小于除数,则上0,余数低位补0得出新的余数。

所以,除法运算的笔算每次上商是1还是0,关键是看余数和除数之间的大小关系比较。笔算中我们都是通过心算进行大小比较,但是,机器没有所谓“心算”,只能在余数和除数之间做减法操作,查看结果正负来判断大小关系。如果余数减去除数的结果为正,说明应该上商为1,而将减法的结果低位补0,就得到新的余数;而如果余数减去除数的结果为负,说明应该上商0,减法的结果无意义,恢复余数法的做法是,将减法结果加上除数,还原减法操作前的余数,然后再将余数低位补0,得到新的余数。

从上面除法运算笔算 例子的竖式中可以看出,余数和除数之间的减法操作,在计算机中实际上使用的是加法器,将减法转换为补码加运算的方法实现的。设余数为A,除数为B,则:

[A-B]补=[A+(-B)]补=[A]补+[-B]补

观察笔算除法竖式发现,每次上商后,除数都需要右移一位来与新的余数对齐,机器字长为5的除法运算需要加法器的位数至少为9,。计算机中,我们可以对笔算算法稍作改变,除数右移一位的操作可以用余数左移一位来代替。这样就不需要在余数和新除数前加连续的0.但左移后的余数已经不是真正的余数,只有再将余数重新右移才能得到真正的余数。

笔算求商时,商的结果是从高位到低位逐位算出来的。在计算机的实现中,计算出每一位的商以后,并不是直接把结果写到寄存器相应的位中,而是从高位开始,将每一位的商写到寄存器的最低位,然后左移一位,等待下一位商写到寄存器的最低位,再左移,再求下一位商……如此循环直到最低位写到寄存器中。

此外,定点小数的除法,如果被除数的绝对值大于或等于除数的绝对值,那么很明显,除法结果的绝对值会大于或等于1,即商成为一个非纯小数。无法再用定点小数表示。并且,除法运算应该避免被除数和除数为0.所以,设被除数为X,除数为Y,X*和Y*分别为X和Y的绝对值。定点小数的除法必须满足下面的条件:

0<|被除数|<|除数|

【例】设二进制纯小数X=-0.1001,Y=0.1101,请使用恢复余数法,计算并列出执行X/Y的操作过程。

求X和Y的原码,得

[X]原=1.1001,[Y]原=0.1101

首先判断符号位:

Zf=Xf异或Yf=1异或0=1

求x和y的绝对值,得

X*=0.1001,Y*=0.1101

求X*和Y*的原码,得

[X*]原=0.1001,[Y*]原=0.1101

求X*、Y*和-Y*的补码,得

[X*]补=0.1001,[Y*]补=0.1101,[-Y*]补=1.0011

余数恢复法执行过程如下:

①余数R=X*.商为0.0000.

②[R]补=[R-Y*]补=[R]补+[-Y*]补=0.1001+1.0011=1.1100,结果为负数。

③商的末尾置0,为0.0000,左移一位,还是0.0000;余数还原:[R]补+[Y*]补=1.1100+0.1101=0.1001;余数左移一位,末位补0,得[R]补=1.0010.

④[R]补=[R-Y*]补=[R]补+[-Y*]补=1.0010+1.0011=0.0101,结果为正数。

⑤商的末位置1,为0.0001,左移一位,得商为0.0010;余数左移一位,末位补零,得[R]补=0.1010

⑥[R]补=[R-Y*]补=[R]补+[-Y*]补=0.1010+1.0011=1.1101,结果为负数。

⑦商的末尾置0,为0.0010,左移一位,得商为0.0100;余数还原:[R]补=[R]补+[Y*]补=1.1101+0.1101=0.1010;余数左移一位,末位补零,得[R]补=1.0100

⑧[R]补=[R-Y*]补=[R]补+[-Y*]补=1.0100+1.0011=0.0111,结果为正数。

⑨商的末尾置1,为0.0101,左移一位,得商为0.1010;余数左移一位,末尾补零,得[R]补=0.1110

⑩[R]补=[R-Y*]补=[R]补+[-Y*]补=0.1110+1.0011=0.0001,结果为正数。

①①商的末位置1,为0.1011.

数值运算结果和符号结果结合,得[X/Y]原=1.1011

总结:首先根据计算位数设商为0.0000(本题的小数点后的精度为4,超出的均为溢出丢弃),然后根据[R]补=[R-Y*]补=[R]补+[-Y*]补的运算结果正负,来确定商的末尾置0还是置1(负数置0,正数置1),并且在每次计算后,计算结果都要左移一位,末尾补零,得到新的余数,然后再用这个新的余数进行计算(同样的公式)。记得这一点差别,商的末位无论置0还是置1,也需要左移,但是在下一步进行置0或是置1是在未移动的结果上进行置0或置1(不能用移动后的商)。同时,如果余数计算的结果为负,那就要恢复余数,也就是用余数再加上除数,然后再进行下面的操作。对于循环几次,取决于除数的位数,本题中除数小数点位数为四位,所以要移动四次,得到最后的结果便是结果(这时无符号位),最后我们再加上一开始判断的符号位便是最终结果。

(3)加减交替法实现数值部分除法。加减交替法也称不恢复余数法,是对恢复余数法的一种改进算法。恢复算法每次用余数减去除数,都是为了观察余数和除数的大小关系,如果减法结果为负数,说明余数小于除数,那么就必须将结果再加除数来还原余数。反复的加减操作很大程度上影响了恢复余数法的运算效率。

再次分析原码恢复余数法发现,余数减去除数,设结果为r:

如果R>0,上商1,R 左移一位,低位补0,就得到新的余数。下一步新的余数再减除数,确定下一位商的结果。也就是说,如果R>0,确定下一位的商和r值的运算为:

R=2R-Y*

如果R<0,上商0,然后需要恢复余数,即R+Y*,将R+Y*的结果再左移一位,低位补0,就得到新的余数。下一步新的余数再减去除数,确定下一位商的结果。也就是说,如果R<0,确定了下一位商和R值的运算为:

R=2(R+Y*)-Y*                即R=2R+Y*

如此一来,当每次余数减除数的结果R为正或者负时,我们只需要根据正负上商,并按照不同公式计算新R的值来确定下一位商即可。不需要在进行当R为负数时恢复余数这样繁琐的操作了。

【例】设二进制纯小数X=-0.1001,Y=0.1101,请使用加减交替法,计算并列出执行X/Y的操作过程。

求X和Y的原码,得

[X]原=1.1001,[Y]原=0.1101

首先判断符号位:

Zf=Xf异或Yf=1异或0=1

求X和Y的绝对值,得X*=0.1001,Y*=0.1101

求X*和Y*的原码,得

[X*]原=0.1001,[Y*]原=0.1101

求X*、Y*、-Y*的补码,得

[X*]补=0.1001,[Y*]补=0.1101,[-Y*]补=1.0011

加减交替法的执行过程如下:

①设余数R=X*=0.1001,商为0.0000.

②[R]补=[R-Y*]补=[R]补+[-Y*]补=0.1001+1.0011=1.1100,结果为负数。

③商的末位置0,为0.0000,左移一位,还是0.0000

④[R]补=[2R+Y*]补=2[R]补+[Y*]补=1.1000+0.1101=0.0101,结果为正数。

⑤商的末位置1,为0.0001,左移一位,得商为0.0010。

⑥[R]补=[2R-Y*]补=2[R]补+[-Y*]补=0.1010+1.0011=1.1101,结果为负数。

⑦商的末位置0,为0.0010,左移一位,得商为0.0100.

⑧[R]补=[2R+Y*]补=[2R]补+[Y*]补=1.1010+0.1101=0.0111,结果为正数。

⑨商的末位置1,为0.101,左移一位,得商为0.1010.

⑩[R]补=[2R-Y*]补=[2R]补+[-Y*]补=0.1110+1.0011=0.0001,结果为正数。

①①商的末位置1,得商为0.1011

数值运算结果和符号结果结合,得[X/Y]原=1.1011

总结:加减交替法采用了公式计算,前面和不恢复余数法一样,计算符号位,设余数为被除数,商为0,[R]补=[R-Y*]补=[R]补+[-Y*]补计算,而下面需要根据结果的正负来使用公式,如果结果为负数,则用R=2R+Y*计算出余数,然后再进行判断。如果结果为正数,则用R=2R-Y*计算,然后判断正负。循环的次数和不恢复余数法一样,由除数决定。最后循环结束再结合符号位就是最终的结果。

浮点数的加减运算

浮点数与定点数相比,所表示的范围更宽,有效精度更高,更加适合于科学计算。但浮点数的格式比定点数要复杂,硬件电路更复杂,实现的成本更高。一些微处理器自身不带有浮点运算功能,但另外配有协处理器,专门用于浮点数的四则运算。

我们在前面讨论了浮点数在机器中的表示方法。阶码E采用补码或移码的方式表示;尾数F采用原码或补码方式表示。设有两浮点数X和Y进行加减运算时,必须按以下几步执行。

1.对阶

使X和Y的小数点位置对齐。才可以进行加减操作。

由于阶码不同,X和Y的尾数的对应位所代表的权值是不同的。加减操作前,必须将X和Y的小数点位置对齐,也就是使X和Y的价码相等。对阶的原则是阶码小的数进行调整,打破浮点数规格化的要求,使两个数的价码相等。例如:

设二进制浮点数X=101.1和Y=1.011,如果要执行X+Y。首先看X和Y在计算机中用N=2^E*F的形式表示,使用规格化形式,为:

X=2^3  *  0.101100

Y=2^1  *  0.101100

X和Y的价码分别为3和1,尾数不能直接相加。按照阶码小的数向阶码大的数对齐原则,调整后的Y的表示为:

Y=2^3  *  0.001011

2.尾数加减

将对阶后的两尾数按定点加减运算规则进行操作,尾数的加减运算一般使用变形补码的加减运算方式来实现。

继续上面的例子,X和Y对阶完成后,尾数就可以进行加运算:

[0.101100]补`=00.101100

[0.001011]补`=00.001011

[0.101100+0.001011]补`=[0.101100]补+[0.001011]补`=00.101100+00.001011=00.110111

3.规格化

为增加有效数字的位数,提高运算精度,必须将求和(差)后的位数规格化。规格化又分为左规和右规两种:

(1)左规。当尾数的变形补码加减运算结果出现00.0***或11.1*****时,说明加减操作无溢出,并且,最高数值位表明,尾数不符合规格化要求,需左规。左规时尾数左移一位,阶码减一,直到符合补码规格化表达式为止,即结果为00.1********或11.0****

(2)右规。当尾数出现01.********或10.**********时,表示尾数的变形补码加减运算结果溢出。在这定点加减运算中是不允许的,但在浮点运算中这不算溢出,可通过右规处理后继续使用。右规时尾数右移一位,阶码加一。

继续上面的例子,执行完尾数加减操作后,X+Y的结果为:

Z=2^3*0.110111

结果符合规格化要求,所以X+Y的结果即为上式。用实数方式表示为:X+Y=(110.111)2进制

【例】两浮点数X=2^+010   *  0.110100,Y=2^+100  *  (-0.101010),求X+Y

阶码取三位,尾数取6位(均不包括符号位),设阶码和尾数均采用补码表示方式,机器表示的形式分别为:

[X]补=0010 0110100

[Y]补=0100 1010110

第一步,对阶:先求阶差(两阶码的补码相减),减去正数补码0100就是加负数补码1100,使用变形补码方式执行:

00 010+11 100=11 110

结果的真值为-2,即X的阶码比Y的阶码小2.[X]补的阶码增大成0100,尾数右移两位,即

[X]补=0100 0001101

第二步:尾数以变形补码的形式相加:

00.001101+11.010110=11.100011

相加结果为:0100 1100011

第三步:规格化:

最高有效位与符号位相同,需要左规,尾数左移一位,阶码减1,结果为:

[X+Y]补=0011 1000110,即

X+Y=2^+011  *  (-0.111010)             【补码的补码即为原码】

4.舍入

在对阶和右规的过程中,可能会将尾数的低位丢失,引起误差,影响了精度,为此可以用舍入法来提高尾数的精度。常用的舍入法有三种:截去法、“恒置1”法和“0舍1入”法。

截去法最简单,不用考虑 右移操作导致丢失的数据,直接丢弃。

“恒置1”法也不考虑右移操作导致被丢掉的数据,而是直接将右移操作后的末尾恒置"1".从统计学角度看,“恒置1”法的平均误差为0,与截去法相比,有更高的可能性使结果更加准确。

“0舍1入”法类似于十进制运算中的“四舍五入”法,即在尾数右移时,如果被移去的数值的最高位为0,则直接舍去;如果被移去的数值最高位为1,则在新尾数的末位加1.这种方法可以保证最大误差是最低误差上的-1/2到1/2之间,正误差可以和负误差抵消。是比较理想的方法,但实现起来比较复杂。并且有可能使尾数又溢出,如果溢出则再做一次右规。

【例】两浮点数X=2^+10  *  0.1101,Y=2^+01  *  0.1011,求X+Y,舍入用“0舍1入法”。

阶码取三位,尾数取四位(均不包括符号位),设阶码和尾数均采用补码表示方式,机器表示的形式分别为:

[X]补=0010 01101

[Y]补=0001 01011

第一步,对阶,我们换一种方式,通过观察,我们发现Y的阶码比X的阶码小1,所以把Y的阶码编程0010,需要尾数右移,即01011右移一位,为00101,题目要求用0舍1入法,我们舍去的为1,所以尾数要加1,所以最终的位数为00110.[Y]补=0010 00110

第二步,尾数以变形补码形式相加

00.1101+00.0110=01.0011

第三步,规格化

因位数符号位为01,需要右规(尾数右移一位,阶码加1),右移后的位数结果为:01001.根据“0舍1入”法可知,尾数被移去一位,该位为1,所以尾数右移一位后末位要加1,即01010,得

[X+Y]补=0011 01010

浮点数的乘法和除法运算

按照数学运算公式,我们知道,两个浮点数相乘,乘积的阶码等于两个乘数的阶码之和,乘积的尾数等于两个乘数的尾数的相乘;两个浮点数相除,商的阶码等于被除数的阶码减去除数的阶码,商的尾数等于被除数的尾数除以除数的尾数。设浮点数X和Y分别为:

X=2^EX  *  Fx

Y=2^EX  *  Fy

X  *  Y=2^(EX+EY)  *  (Fx  *  Fy)

X  /  Y=2^(EX-EY)  *  (Fx/Fy)

一般乘除法运算之前,首先会检测能否简化操作。比如,检测乘法(除法)是否有乘数(被除数)为0,如果有乘数(被除数)为0,那么乘积(商)必为0.

从数学运算公式就可以看出,浮点数的乘法和除法主要包括两组定点运算,分别为定点整数的阶码加减和定点小数的尾数乘除运算。尤其是除法运算中的尾数除法运算,要注意被除数尾数的绝对值是否小于除数尾数的绝对值,以确保商的尾数为小数。如果不是,则需要调整阶码,将被除数尾数右移一位,价码加1,然后再执行除法运算。

最后,乘除运算过程也要考虑规格化和舍入的问题,以及溢出问题,尤其是阶码加减运算比较产生溢出。

猜你喜欢

转载自blog.csdn.net/mez_Blog/article/details/102923073
今日推荐