1. 程式人生 > >[深入理解計算機系統] 計算機如何實現乘法與除法運算

[深入理解計算機系統] 計算機如何實現乘法與除法運算

乘法運算

(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-1yi yi-yi-1 操作
00 0 加上0,即直接右移一位
01 1 加上[X]補,再右移一位
10 -1 加上[-X]補,再右移一位
11 0 加上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,否則視為“溢位”。

定點整數同理。