[深入理解计算机系统] 计算机如何实现乘法与除法运算

乘法运算

(1)原码一位乘法

算法要点:(1)乘法通过加法和移位来实现。两个5位二进制数(最高位为符号位)相乘,共需要进行4次加法和4次移位。

                 (2)部分积总是先加上被乘数或零,然后右移1位得到新的部分积。

                (3)部分积是加上被乘数还是加上零,取决于乘数中当前考虑的数位。该数位为1,则加上被乘数然后右移,否则直接右移。

                (4)乘数中的数位一旦被考虑过,将不再需要,可以通过右移丢弃。

                (5)部分积加上被乘数的过程中,数值最高位产生的进位可能会占据符号位。但是由于乘法中符号位是单独处理,所以被乘数,乘数和部分积都被认为是无符号位数,而且做完加法之后肯定要右移1位,因此这里出现的“进位占据符号位”的现象不算“溢出”,右移后符号位0将还原。

例:已知X=0.1010B,Y=-0.0111B,用原码一位乘法求X*Y=?

因为X=0.1010B,Y=-0.0111B,所以

[X]原=0.1010,X*=0.1010,x0=0;

[Y]原=1.0111,Y*=0.0111,y0=1;

部分积                               乘数                                        注释

  0.0000                             011                                       此时乘数为0111,开始时,部分积Z0=0;

+0.1010                                                                            乘数中当前考虑的数位为1,加上X*  

 

  0.1010

  0.0101   -> (0右移)          0  011       (1右移舍去)           右移一位得新部分积Z1

+0.1010                                                                            乘数中当前考虑的数位为1,加上X*


  0.1111

  0.0111   -> (1右移)           10  01        (1右移舍去)          右移一位得新部分积Z2

+0.1010                                                                           乘数中当前考虑的数位为1,加上X*


  1.0001

  0.1000   -> (1右移)           110  0       (1右移舍去)          右移一位得新部分积Z3

+0.0000                                                                           乘数中当前考虑的数位为0,加上0


  0.1000

  0.0100                             0110                                        右移一位得新部分积Z4

[X*Y]原 的符号位=x0⊕y0=0⊕1=1

所以X* * Y* =0.01000110 ,则[X*Y]原=1.01000110,X*Y=-0.01000110

原码一位乘法的实现虽然比较简单,但是由于计算机都是采用补码来进行加,减运算,如果为了做乘法运算而将操作数从补码转换成原码,运算结束后再从原码转换成补码,这样就增加了许多操作步骤,延迟了计算时间。为此,人们又研究了补码乘法方法,实现了基于补码的乘法器,这样就进一步提高了乘法运算的效率。

(2)补码一位乘法

补码一位乘法是把乘数Y补码的符号位设成0,当做一个正数,与被乘数补码相乘。乘法运算的步骤与原码乘法相同。乘积出来后,如果Y是负数,则加上[-X]补得到[X*Y]补;否则乘积就直接等于[X*Y]补。这样的补码一位乘法也称校正法。

例:已知X=0.1010B,Y=-0.0111B,用校正法求X*Y=?

被乘数补码为[X]补=0.1010B,乘数补码为[Y]补=1.1001。由于Y是负数,所以将其符号位去掉,故参与运算的乘数是0.1001。乘积出来后加上[-X]补进行校正。[-X]补=1.0110。

考虑到运算时可能会出现部分积的绝对值大于1的情况,所以被乘数和部分积采用双符号位。

部分积                               乘数                                        注释

  00.0000                            100                                       此时乘数为1001,开始时,部分积Z0=0;

+00.1010                                                                            乘数中当前考虑的数位为1,加上[X]补  

 

  00.1010

  00.0101   -> (0右移)          0  100       (1右移舍去)           右移一位得新部分积Z1

+00.0000                                                                           乘数中当前考虑的数位为0,加上0


  00.0101

  00.0010   -> (1右移)           10  10        (0右移舍去)         右移一位得新部分积Z2

+00.0000                                                                           乘数中当前考虑的数位为0,加上0


  00.0010

  00.0001   -> (0右移)           010  1       (0右移舍去)          右移一位得新部分积Z3

+00.1010                                                                           乘数中当前考虑的数位为1,加上[X]补


  00.1011

  00.0101    -> (1右移)          1010        (1右移舍去)           右移一位得新部分积Z4

+11.0110                                                                            加上[-X]补进行校正

  11.1011                             1010

结果为[X*Y]补=1.10111010,所以X*Y=-0.01000110B。

采用补码进行乘法,乘积的符号是在计算中自然得到的,这是补码运算的一个共同特点,也是与原码乘法的一个重要区别。

(3)布斯算法

上述校正法的运算过程与乘数的符号有关。虽然可以将被乘数与乘数交换位置,使得乘数尽可能为正,以避免校正操作。但是当被乘数与乘数均为负数时,校正操作就不可避免了,所以校正法的控制逻辑比较复杂。为此,英国计算机专家布斯(A.D.Booth)于1956年提出了不用考虑操作数符号,可以用统一的规则进行计算的“布斯算法”。


yi-1yiyi-yi-1操作
000加上0,即直接右移一位
011加上[X]补,再右移一位
10-1加上[-X]补,再右移一位
110加上0,即直接右移一位

例:已知X=0.1010B,Y=-0.0111B,用布斯算法求X*Y=?

被乘数补码为[X]补=0.1010B,乘数补码为[Y]补=1.1001,校正数[-X]补=1.0110。

注意,布斯算法属于补码乘法运算,符号位是参与运算的。

部分积                               乘数                 附加位                       注释

  00.0000                            1100 1                  0                            此时乘数为11001,开始时,部分积Z0=0;

+11.0110                                   yi-1               yi                           yi-1yi为10,加上[-X]补

 

 

  11.0110

  11.1011   -> (0右移)          0  110 0                 1                            右移一位得新部分积Z1

+00.1010                                                                                    yi-1yi为01,加上[X]补


  00.0101

  00.0010   -> (1右移)          10  11 0                 0                          右移一位得新部分积Z2

+00.0000                                                                                     yi-1yi为00,加上0


  00.0010

  00.0001   -> (0右移)           010 1 1                 0                          右移一位得新部分积Z3

+11.0110                                                                                     yi-1yi为10,加上[-X]补


  11.0111

  11.1011    -> (1右移)          1010  1                 1                           右移一位得新部分积Z4

+00.0000                                                                                     yi-1yi为11,加上0

  11.1011                            1010  1                                               第5步运算结束后,不再右移

结果为[X*Y]补=1.10111010,所以X*Y=-0.01000110B。


除法运算

(1)原码恢复余数除法

原码除法的特点是:符号位单独处理,操作数的绝对值相除。

例:设被除数X=+0.1010B,除数Y=-0.1101B。求X/Y=?

[X]原=0.1010B,[Y]原=1.1101B,所以商的符号等于0⊕1=1。

记X的绝对值为X*=0.1010B,Y的绝对值为Y*=0.1101B。则商的绝对值等于X*/Y*。

由于要做“余数(被除数)减去除数”的操作,而在计算机中这个操作是通过“余数(被除数)加上负的除数的补码”来完成的,所以给出[-Y*]补。

因为[Y*]补=0.1101B,所以[-Y*]补=1.0011B。

操作                    被除数(当前余数)                           填商                                        注释

                            00.1010

加上 [-Y*]补         +11.0011

                            11.1101                                             0                                             余数为负,上商0


加上[Y*]补          + 00.1101

                            00.1010                                                                                            恢复余数

左移1位                 01.0100                                            0

加上 [-Y*]补         +11.0011

                            00.0111                                           01                                             余数为正,上商1

左移1位                00.1110                                            01

加上 [-Y*]补        +11.0011

                           00.0001                                            011                                            余数为正,上商1

左移1位                00.0010                                          011

加上 [-Y*]补        +11.0011

                           11.0101                                           0110                                          余数为负,上商0

加上[Y*]补          +00.1101

                           00.0010                                                                                             恢复余数

左移1位               00.0100                                          0110                                           

加上 [-Y*]补        +11.0011                

                           11.0111                                           01100                                          余数为负,上商0

加上[Y*]补          +00.1101                      

                           00.0100                                                                                             恢复余数(最终余数)                        
                                     

所以X*/Y*的商是0.1100B,余数为0.0100B*2^(-4)=0.00000100B

由于在这个原码算法中,一旦上商0。就需要恢复余数后才能计算下一位商。故称其为“恢复余数除法”。由于它在计算过程中需要恢复余数,所以运算速度变慢,而且恢复余数的次数事先是未知的,所以运算步数不能预先确定,这会使控制逻辑变得复杂。


(2)原码加减交替除法

操作                    被除数(当前余数)                           填商                                        注释

                            00.1010

加上 [-Y*]补         +11.0011                                                                                           减去除数

                            11.1101                                             0                                             余数为负,上商0


左移1位                11.1010                                            0

加上[Y*]补          +00.1101                                                                                            加上除数

                           00.0111                                             01                                            余数为正,上商1


左移1位               00.1110                                             01                     

加上 [-Y*]补       +11.0011                                                                                              减去除数

                          00.0001                                            011                                           余数为负,上商0


左移1位              00.0010                                            011

加上 [-Y*]补      +11.0011                                                                                                减去除数

                         11.0101                                              0110                                          余数为负,上商0


左移1位              10.1010                                            0110

加上[Y*]补        +00.1101                                                                                                加上除数

                         11.0111                                              01100                                          余数为负,上商0

加上[Y*]补        +00.1101                                                                                                加上除数

                         00.0100                                                                                                恢复余数(最终余数)

所以X*/Y*的商是0.1100B,余数为0.0100B*2^(-4)=0.00000100B

对于计算机的定点小数除法而言,商也必须是定点小数。这就要求被除数的绝对值必须小于除数的绝对值、也就是说,第一次上商必须是0,否则视为“溢出”。

定点整数同理。







  • 14
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值