本文采用4位二進制數的例子,從表象對原碼反碼補碼進行探究,旨在說明為什么計算機底層要用補碼表示數字以及用補碼表示數字的優點,不涉及任何數學原理。
4位二進制數的原碼表示:
| +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 |
|---|---|---|---|---|---|---|---|
| 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 |
|---|---|---|---|---|---|---|---|
| 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
- 4位二進制數有16中不同的編碼方式,可以對應16個不同的二進制數。為了表示正負,把最高位作為符號位,0正1負。所以采用這種方式表示的10進制數為(-7,-0)∪(+0,+7)。
- 雖然可以表示這16個數了,但是仍存在計算問題,我們希望在計算機中只進行加法運算,並且硬件在計算時不用判斷符號位。現在我們嘗試一下能否實現:(+1)-(+2)=(+1)+(-2)=0001+1010=1011=(-3),顯然這個等式是錯誤的。因此,如果要正確計算,還需要制定一套比較復雜的運算規則,這會加大計算機硬件的設計復雜度。
4位二進制數的反碼表示:
| +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 |
|---|---|---|---|---|---|---|---|
| 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 |
|---|---|---|---|---|---|---|---|
| 1111 | 1110 | 1101 | 1100 | 1011 | 1010 | 1001 | 1000 |
- 解決的辦法是運用某些數學原理(限於腦力與時間,這里不做深究)將負數的表示進行重新編碼,這里並不會打擾到之前已經編好的正數的編碼。可以看到,這里只相當於用原來-7的編碼表示-0,-6的編碼表示-1……
- 這樣就解決了運算問題,還是上面的例子:(+1)-(+2)=(+1)+(-2)=0001+1101=1110=(-1),得到了正確的結果。在這次計算時,硬件只進行了加法運算,並且硬件在處理二進制時也沒有考慮符號位,但仍得到了正確的結果。
- 雖然看似已經解決了計算問題,但是仍存在一個缺點:+0=0000,(+0)+(+1)+(-1)=0000+0001+1110=1111=(-0)。我們不需要+0和-0這兩個0。
4位二進制數的補碼表示:
| +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 |
|---|---|---|---|---|---|---|---|
| 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 |
|---|---|---|---|---|---|---|---|---|
| 0000 | 1111 | 1110 | 1101 | 1100 | 1011 | 1010 | 1001 | 1000 |
- 解決的辦法是我們再次對負數進行重新編碼,這次的改變是將所有的負數編碼在之前的基礎上加1,這仍然不會影響到之前已經編好的正數的編碼。
- 可以看到現在+0和-0的編碼都變成了0000,也就只有1個0了。再次進行上例的計算,0+(+1)+(-1)=0000+0001+1111=0000=0。0的問題也得到了解決。
- 同時,由於只剩下了一個0,那么現在16個編碼對應了15個數字,即(-7,7),可以發現1000並沒有對應任何十進制數。-8=(-7)+(-1)=1001+1111=1000,所以我們可以讓1000對應-8。
- 至此在計算機中使用此種編碼方式,既做到了讓硬件只進行加法運算且硬件可以無視符號位,也解決了0的問題,可以讓4位二進制數可以真真正正地表示16個數字。
