補碼的理解(-128的補碼解釋)


作者:何新宇
鏈接:https://www.zhihu.com/question/20159860/answer/21113783
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

以前寫過一篇blog: 補碼、負數和減法,盡管不是很對題,但依然希望能給題主帶來幫助
---

背景

復習c++的時候遇到二進制編碼問題,上網搜索了一番,終於有點眉目。 一般來說,初學二進制編碼時,會看到如下描述

原碼表示法是機器數的一種簡單的表示法。其符號位用0表示正號,用:表示負號,數值一般用二進制形式表示。

機器數的反碼可由原碼得到。如果機器數是正數,則該機器數的反碼與原碼一樣;如果機器數是負數,則該機器數的反碼是對它的原碼(符號位除外)各位取反而得到的。

機器數的補碼可由原碼得到。如果機器數是正數,則該機器數的補碼與原碼一樣;如果機器數是負數,則該機器數的補碼是對它的原碼(除符號位外)各位取反,並在未位加1而得到的。


如果是為了考試,死記即可。但我總想搞清楚為什么計算機里面的數要這樣子表達?意義何在?-128的補碼為什么是10000000?為什么補碼有這么奇怪的運算規則?計算機算減法的時候都需要從源碼到補碼的計算嗎?


思路

google了一下,看到了這樣一篇文章,注意到文中關於補碼來歷的描述,可以總結如下:

  1. 計算機里面,只有加法器,沒有減法器,所有的減法運算,都必須用加法進行。
  2. 用補數代替原數,可把減法轉變為加法。出現的進位就是模,此時的進位,就應該忽略不計。
  3. 二進制下,有多少位數參加運算,模就是在 1 的后面加上多少個 0。
  4. 補碼就是按照這個要求來定義的:正數不變,負數即用模減去絕對值。

補充解釋一下“模”的概念(不准確):
考慮時鍾上時間的計算,假設現在時針指向數字3,若問“6小時前時針指向的數字是幾”,則可以:
1. 將時針逆時針撥動6格。
2. 將時針順時針撥動12 - 6 = 6格。

兩者的結果是一樣的。這里稱12為“模”。
故有 3時 - 6個小時 = 3時 + (12 - 6個小時),這里可以看到將減法轉換成加法的過程,即“加上模減去絕對值的差”。

所以,假設模是10,有效位數為1,當我們計算 9 - 7 的時候:
9 - 7 => 9 + (10 - 7) = 12,去掉最高的位后,得到2,這是正確的結果。
從9 - 7 = 2 和 9 + (10 - 7) = 12可以憑后者比前者多“1”來看出前者中“7”的正負號。

作者的意思是說,計算機里面所有數都以補碼形式保存,加減運算都是補碼之間的加法運算。然后作者提出了一個我之前沒聽過的觀點:

補數 和 補碼的定義式 里面,根本就沒有什么符號位。這最高位的1、0是自然出現的,並不是由人來規定的。


的確,符號位在補碼運算里面是“模”,本身並不帶符號的意義。因為計算機將加法轉換成加上一個“負數”,而負數又以補碼的形式表現。補碼比源碼多一位,從這多出來的一位可以推斷出原來數字的正負號,所以成為了符號位。也可以這樣認為,留出一位(不全部占滿)的原因是要用“模”來表示正負數。


也就是說,不是特意留出一個符號位,用1和0來表示正負號。而是補碼運算可以用最高位來表示正負,所以符號位誕生了。


那么為什么-128的補碼是10000000?可以這樣理解。-128是一個負數,所以它的補碼是它的“模”減去它的絕對值,即:

100000000 - 10000000 = 10000000

那么為什么負數補碼等於源碼的反碼加一呢?可以這樣推導:

100000000 - 10000000 
= (11111111 + 00000001) - 10000000 
= 11111111 - 10000000 + 1 
= 01111111 + 1 //反碼加一
= 10000000

由此我們得知,在計算機里面所有的數字都以補碼形式存儲。127存成01111111,-127存成11111111,算減法就變成算加法了,盡管你看到的是“-”號。

-------

今天讀《計算機組成-結構化方法》后,對這個問題有了新的理解。

將負數用補碼表示,實際上是實現了一種從[-128, 127]到[0, 255]的映射。如下所示:

+----------------------------+
| 255      -1      11111111  |
| 254      -2      11111110  |
| 253      -3      11111101  |
| 252      -4      11111100  |
| 251      -5      11111011  |
| 246      -10     11110110  |
| 236      -20     11101100  |
| 226      -30     11100010  |
| 216      -40     11011000  |
| 206      -50     11001110  |
| 196      -60     11000100  |
| 186      -70     10111010  |
| 156      -100    10011100  |
| 129      -127    10000001  |
| 128      -128    10000000  |
| 127      127     01111111  |
| 100      100     01100100  |
| 70       70      01000110  |
| 60       60      00111100  |
| 50       50      00110010  |
| 40       40      00101000  |
| 30       30      00011110  |
| 20       20      00010100  |
| 10       10      00001010  |
| 5        5       00000101  |
| 4        4       00000100  |
| 3        3       00000011  |
| 2        2       00000010  |
| 1        1       00000001  |
| 0        0       00000000  |
+----------------------------+


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM