現實生活中的除法
爲了便於描述,我們這樣做
步驟:
- 被除數減除數,被除數大,上商爲1,被除數小,上商爲0。
- 每次得到的差爲中間餘數,將除數右移後與中間餘數比較,中間餘數大,上商爲1,中間餘數小,上商爲0。
- 循環步驟2,直到求得商的位數足夠。
預處理
- 被除數爲0,除數不爲0,商爲0。
- 定點整數,被除數小於除數,商爲0。
- 定點整數,被除數不爲0,除數爲0,發生異常。
- 浮點數,被除數不爲0,除數爲0,產生無窮(inf/-inf)。
- 浮點數,被除數和除數都爲0,產生非數(NaN)。
只有除數和被除數都不爲0,商也不爲0時,才進一步除法運算
無符號數的除法
模擬手工
如果兩個n位數相除,需要將被除數擴展爲2n位:
- 正整數:在被除數前加n個0
- 純小數:在被除數後加n個0
根據現實中的除法,得出在機器中運算的關鍵步驟:
- 餘數減除數得一個新餘數
- 新餘數大於0(表明夠減),商左移上1。
- 新餘數小於0(不夠減),商左移上0,並恢復餘數。
- 除數右移
流程圖如下:
比如:求7除2的值?
7的原碼是0111,擴展之後是0000 0111。
2的原碼是0010 0000,變補碼是1110 0000。
商 | 除數 | 中間餘數(默認爲被除數) | 中間餘數減除數 |
---|---|---|---|
0000 | 0010 0000 | 0000 0111 | 0000 0111+1110 0000=1110 0111<0 |
0000 | 0001 0000 | 0000 0111(恢復餘數) | 0000 0111+1111 0000=1111 0111<0 |
0000 | 0000 1000 | 0000 0111(恢復餘數) | 0000 0111+1111 1000=1111 1111<0 |
0000 | 0000 0100 | 0000 0111(恢復餘數) | 0000 0111+1111 1100=0000 0011>0 |
0001 | 0000 0010 | 0000 0011 | 0000 0011+1111 1110=0000 0001>0 |
0011 | 0000 0001 | 0000 0001 | 結束 |
結果是0011,表示商是2,中間餘數是0000 0001,表示餘數是1。
4位數,所以是5步
一開始的上商值是0,移了5次之後,在商中消失了,這個數其實是用來判斷是否溢出的,如果是1,則代表溢出,即商無法用4位數表示。
優化
恢復餘數法
如果被除數和除數都是n位,那麼商一定不溢出,即n位一定可以表示兩n位數的商。
商一開始的有四個沒用的0,中間餘數的前4位都是沒用的0(在被除數是n位的前題下),因此可以合併商和中間餘數,用8位就可表示4位中間餘數和4位商。
如果除數不移動,那麼除數的後4位也多餘,所以想一個辦法代替除數右移,就可以用4位表示除數。
這個辦法就是中間餘數左移(與除數右移效果一樣),所以中間餘數一開始應該放在右4位纔可以左移。
所以最終確定,4位中間餘數與4位商合併,前4位最終表示餘數,後四位最終表示商,用4位表示除數。
除數(4位) | 中間餘數與商的合併位(4+4) | 高4位減除數(4位) |
---|---|---|
0010 | 0000 0111 | 0000+1110=1110<0 (此步應省) |
0010 | 0000 1110(恢復+左移) | 0000+1110=1110<0 |
0010 | 0001 1100(恢復+左移) | 0001+1110=1111<0 |
0010 | 0011 1000(恢復+左移) | 0011+1110=0001>0 |
0010 | 0011 0001(左移) | 0011+1110=0001>0 (此處0001即爲餘數) |
0010 | 0010 0011(左移) | 餘數右移1位 |
因爲合併位左移了5次,中間餘數會多移一次,所以需要將0010右移一次,得到0001纔是正確的餘數。
由於除數和被除數都是n位,合併位的高n位一開始全爲0,所以高n位減除數一定小於0,所以無需第一步判斷差的結果,直接左移合併位並上商爲0即可。
不恢復餘數法(加減交替法)
上面的是恢復餘數之後才左移,當然也可以不恢復餘數。
我們看上面的第一步恢復餘數
除數(4位) | 中間餘數與商的合併位(4+4) | 高4位減除數(4位) |
---|---|---|
0010 | 0000 0111 | 0000+1110=1110<0 |
0010 | 0000 1110(恢復+左移) | 0000+1110=1110<0 |
第一次中間餘數減除數之後,中間餘數變爲1110,之後,1110+0010恢復成0000,然後左移,最低位補0(因爲1110<0)。
我們也可以這樣,第一次中間餘數減除數之後,中間餘數變爲1110,之後,1110 0111左移,最低位補0,變爲1100 1110,然後1100+0010就是下次高4位減除數的結果1110。
除數(4位) | 中間餘數與商的合併位(4+4) | 高4位加/減除數(4位) |
---|---|---|
0010 | 0000 0111 | 0000+1110=1110<0 |
0010 | 1100 1110(左移) | 1100+0010=1110<0 |
這裏高4位是加還是減,取決於合併位的高4位,高4位大於等於0,做減法。高四位小於0,做加法。
最後一次若上商爲0,需糾正餘數,將餘數加除數纔是真正的餘數。
比如5/3,5的二進制是0101,3的二進制是0011,3的變補是1101。
除數(4位) | 中間餘數與商的合併位(4+4) | 高4位加/減除數(4位) |
---|---|---|
0011 | 0000 0101 | 0000+1101=1101<0(減法) |
0011 | 1010 1010(上0) | 1010+0011=1101<0(加法) |
0011 | 1011 0100(上0) | 1011+0011=1110<0(加法) |
0011 | 1100 1000(上0) | 1100+0011=1111<0(加法) |
0011 | 1111 0000(上0) | 1111+0011=0010>0(加法) |
0011 | 0100 0001(上1) | 糾正餘數 |
0100+1101=0001,所以1是餘數,0001是商。
原碼除法
- 符號位和數值位分開處理
- 商和餘數的值按無符號數值算
- 商的符號,被除數與除數同號爲正,異號爲負
- 餘數的符號同被除數符號