點這裡獲得更好的閱讀體驗
補碼(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 插口...