補碼是什麼

點這裏獲得更好的閱讀體驗

2 的補碼(2’s complement),以下簡稱補碼。幾乎所有的計算機都通過補碼來表示有符號整數,在 C 語言中,數據類型 int 代表長度爲 4-Bytes (32-bits) 的有符號數,可表示的範圍爲 [231,2311][-2^{31}, 2^{31} - 1],其中正數部分的補碼與我們的直覺相同,負數的補碼形式需要一些轉換,本文介紹補碼的各種轉換以及其內在的原理。

補碼的轉換算法可總結爲,按位取反再加一,例如要想知道 -30 在計算機中表示的形式(以 8-bits 爲例),可以這樣操作:

先寫出 30 的二進制形式

0 0 0 1 1 1 1 0

按位取反

1 1 1 0 0 0 0 1

再加一

1 1 1 0 0 0 1 0

這就是 -30 的補碼

讀懂補碼

如何知道補碼錶示的數是多少,若最高位爲 0,則代表是正數,可直接按照正常步驟轉化爲十進制,若最高位爲 1,則代表是負數,要知道負數的補碼形式代表的數字,可以先想辦法翻轉補碼的符號,這樣就得到的其正數表示,之後便輕而易舉了。而翻轉符號的方法也是,按位取反再加一

1 1 1 0 0 0 1 0 表示什麼呢?

按位取反

0 0 0 1 1 1 0 1

再加一

0 0 0 1 1 1 1 0

這是二進制形式的 30,於是 1 1 1 0 0 0 1 0 代表的是 -30。

int 的範圍

在介紹部分說到在 C 語言中,數據類型 int 代表長度爲 4-Bytes (32-bits) 的有符號數,可表示的範圍爲 [231,2311][-2^{31}, 2^{31} - 1],這是如何得到的呢?

最小整數

觀察下面這個 32-bits 的數

1000 0000 0000 0000 0000 0000 0000 0000

最高位爲 1,代表是負數,對他進行符號翻轉,按位取反再加一,得到

1000 0000 0000 0000 0000 0000 0000 0000

這是二進制形式的 2312^{31},可知 231-2^{31}int 能表示的最小整數

最大整數

觀察下面這個 32-bits 的數

0111 1111 1111 1111 1111 1111 1111 1111

最高位爲 0,代表是正數

這是二進制形式的 23112^{31} - 1,可知 23112^{31} - 1int 能表示的最大整數

爲什麼選擇補碼

補碼有簡化計算機內部算術單元電路的優勢,若採用補碼,加減法的電路可以統一,請看下面的例子:

計算 16 + 30

  0 0 0 1 0 0 0 0 (16)

- 0 0 0 1 1 1 1 0 (30)
——————————————————————
  0 0 1 0 1 1 1 0 (46)

計算 16 - 30

也即 16 + (-30)

  0 0 0 1 0 0 0 0 (16)

- 1 1 1 0 0 0 1 0 (-30)
———————————————————————
  1 1 1 1 0 0 1 0 (-14)

對於結果 1 1 1 1 0 0 1 0,對其進行符號翻轉 (按位取反再加一) 後得到

0 0 0 0 1 1 1 0

這是二進制形式的 14,與預期相符。

從上面兩個例子可以看出,加減法的算法是統一的。

爲什麼是 “按位取反再加一”

爲什麼 “按位取反再加一” 能夠奏效呢?看看下面這個故事:

要想把正數的符號翻轉,可以通過 0 減去這個正數,就得到了他對應的負數。例如要得到 30 對應的負數:

  0 0 0 0 0 0 0 0 (0)

- 0 0 0 1 1 1 1 0 (30)
——————————————————————
  1 1 1 0 0 0 1 0 (-30)

雖然還可以繼續減下去,但由於我們限制在 8 位,因此計算機不會繼續計算了。

發現了嗎,得到的結果是 -30 的補碼。但其實這樣算和用 2n2^n (此處 n = 8,代表一個 1 後跟了 8 個 0) 減去 30 是一樣的,因爲我們一直在像高位“借一”:

  1 0 0 0 0 0 0 0 0 (2^8)

-   0 0 0 1 1 1 1 0 (30)
————————————————————————
  0 1 1 1 0 0 0 1 0 (-30)

1 0 0 0 0 0 0 0 0 正好等於 8 個 1 再加 1:1 1 1 1 1 1 1 + 1,而用 1 1 1 1 1 1 1 1 減去一個數相當於對這個數按位取反。

這就是按位取反再加一背後的故事。

參考

Two’s Complement, Cornell
關於 2 的補碼, 阮一峯

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