定點除法運算

計算機中,除法運算和乘法運算一樣,是非常常用的一種運算。同樣,除法運算在計算機中的實現也分爲符號部分和數值部分兩部分。

(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

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

                    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,然後再執行除法運算。

最後,乘除運算過程也要考慮規格化和舍入的問題,以及溢出問題,尤其是階碼加減運算比較產生溢出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章