補碼是什麼

2021-10-03 10:10:02 字數 3517 閱讀 8123

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

補碼(2』s complement)是計算機用於表示諸如 +20,-17 這樣有符號整數的方式。如在 c 語言中(或者許多其他的靜態型別語言),整形資料型別int代表長度為 4-bytes (32-bits) 的有符號數,可表示的範圍為 [−2

31,231

−1

][-2^, 2^ - 1]

[−231,

231−

1],這個範圍裡的數字有正有負,都是有符號數,而他們在計算機中就是通過補碼來表示的。在這些有符號數里正數的補碼與我們的直覺相同,但負數的補碼形式需要一些轉換,本文介紹如何得到乙個數的補碼,如何讀懂補碼以及補碼內在的原理。

-30 在計算機中是如何表示的呢?首先我們認為它是乙個有符號整數,那麼在計算機中就是用補碼表示的,如何得到它對應的補碼形式?首先給出結論:按位取反再加一,下面以 8-bits ,即八位二進位制位為例,計算-30 的補碼:

先寫出 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 的補碼

30 與我們的直覺相同,就是 30 的二進位制形式0 0 0 1 1 1 1 0

如果給我們乙個補碼,例如上文得到的 -30 的補碼,我們如何能知道這個補碼表示的數是多少呢,同樣,這裡先給出結論:若補碼最高位為 0,則代表是正數,可直接按照正常步驟轉化為十進位制,就像上文得到的 30 的補碼就是 30 的二進位制形式一樣,若最高位為 1,則代表是負數,要知道負數的補碼形式代表的數字,可以先想辦法翻轉補碼的符號,這樣就得到的其正數表示,而正數的補碼形式又可以直接轉化為 10 進製,最後就可知道它代表的是哪個負數了!而翻轉符號的方法也是,按位取反再加一

有如下最高位為 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。

在介紹部分說到在 c 語言中,資料型別int代表長度為 4-bytes (32-bits) 的有符號數,可表示的範圍為 [−2

31,231

−1

][-2^, 2^ - 1]

[−231,

231−

1],這是如何得到的呢?

觀察下面這個 32-bits 的數

1000 0000 0000 0000 0000 0000 0000 0000

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

1000 0000 0000 0000 0000 0000 0000 0000

這是二進位制形式的 2

312^

231,可知 −231

-2^−2

31是int能表示的最小整數

觀察下面這個 32-bits 的數

0111 1111 1111 1111 1111 1111 1111 1111

最高位為 0,代表是正數

這是二進位制形式的 231−

12^ - 1

231−

1,可知 231−

12^ - 1

231−

1 是int能表示的最大整數

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

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)

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 減去它就得到 -30。下面看看如何得到二進位制形式 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)

可以看到高位一直在出現 1,因為我們一直在向高位借一,雖然還可以繼續減下去,但由於我們限制在 8 位,因此計算機不會繼續計算了。

發現了嗎,得到的結果其實就是 -30 的補碼形式。在計算過程中,我們一直在向高位借一,那為什麼不在被減數 0 的最高位之前再加上乙個 1 來滿足這無休止的借位呢?

因此對於乙個 n 位的二進位制數,要得到與之符號相反的數,可以用 2

n2^n

2n減去它。例如此處 n = 8(數字上也就代表乙個 1 後跟了 8 個 0),要得到與 30 符號相反的數,可以用 2

82^8

28減去,即下面這個算式:

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 (2^8)等於 (28

−1)+

1(2^8 - 1) + 1

(28−1)

+1,即 8 個 1 再加 1:1 1 1 1 1 1 1 + 1,而用其中的1 1 1 1 1 1 1 1減去乙個數就相當於對這個數按位取反,另一部分+ 1就是加一。

總結起來就是按位取反再加一

two』s complement by cornell

關於 2 的補碼 by 阮一峰

什麼是補碼,怎麼求補碼

由此產生的疑惑更多了 到底什麼是符號位?進而補碼又是什麼?理由很簡單,計算機內部只有加法器,並沒有減法器 所以在計算機中,在我們人類眼中很簡單的算術運算2 3 1 計算機是無法完成的,那麼依照計算機只能做加法,很顯然的想到了2 3 1 因此數在計算機中必然要有特定的表示,那麼補碼就誕生了。無符號 u...

你是什麼就是什麼!

不管到了什麼樣的年紀,我們都很難放棄對外表的一些執著吧。我一直要到遇見了乙個很特別很特別的人,從他身上,我才真正的懂了 外表之於乙個人的真正意義是什麼 去年,我買了新房子,本來是想委託我的小學同學幫我做室內設計,但是因為一些因素,他推薦了他口中比他更厲害的大師級設計師哥哥給我,他說大哥一直都做大飯店...

HIDL是什麼,Binder是什麼?

hidl可以用於程序間通訊 ipc 而程序間的通訊通常採用binder機制 binder是android系統程序間通訊 ipc 方式之一。linux已經擁有的程序間通訊ipc手段 internet process connection 包括 管道 pipe 訊號 signal 跟蹤 trace 插口...