補碼與符號位取反

2022-08-31 09:15:07 字數 1208 閱讀 2877

先來乙個 c 語言的小例子:

#include #include int main(void)

對於16位的整數 n ,按位與執行將最高位設定為0(符號位),得到的結果卻不是 1 ,結果是 32767 。

原因在於有符號整數的實現方式。

有符號整數,最容易想到的方式是在最高位加乙個符號位,0表示整數,1表示負數,其它位不變(保留原始值),也即是原碼方式。但這個方式有乙個問題,存在兩個0,正0和負0,在計算時需要先判斷符號位,然後才能決定用加法還是減法,機器計算不便。

另外乙個方法是負數全部按位取反,也就是反碼方式。這個運算就相對簡單了,進行加法時,按位計算,0和0為0,0為1為1,1和1為0並產生進製,最高位有進製時,結果要加1,減法可處理為其負數的加法。但還是有點問題,還存在兩個0,正0和負0。

問題是出現負數上,那麼把負數的反碼 + 1 ,不就把負0去掉了嗎?還真的是這樣,而同時負數比整數能多表示乙個數(這是基於同餘的)。

嚴格的表達為:

對於位數為 n 的整數,其補碼 [x]補 為:(2^n + x) mod 2^n ,

表示的範圍為 -2^(n-1) <= n < 2^(n-1) ,注意正數最大為 2^(n-1)-1

即:當 0 <= x < 2^(n-1) 時,

[x]補 = x 的原碼

當 -2^(n-1) <= x < 0 時,

[x]補 = 2^n + x 的原碼。

而經驗上,可看作負數的補碼為其反碼加1(特殊數 -2^(n-1) ) 的反碼 :

x < 0 時:

[x]補 = [x]反 + 1

特殊數 [ -2^(n-1) ] = 100...0

它的加法處理非常簡單,符號位也可以執行,

[x+y]補 = (2^n + x + y) mod 2^n = ((2^n + x) + (2^n + y)) mod 2^n = [x]補 + [y]補

[x-y]補 = (2^n + x - y) mod 2^n = ... = [x]補 + [-y]補

現在回到原來的問題,對於16位 -1 ,其補碼為:

[-1]補 = [-1]反 + 1 = 0xfffff
按位與去掉符號位,得到的是 0x7fff 也就是16位整數最大的正數( 2^15 - 1) 32767。

位運算(取反 補碼 左移 右移 與 或)

4.右移 5.與6.或 7.異或 8.位運算的應用 ending 1 將參加運算的兩個數轉換為二進位制,若預設為int則有32位,這裡預設為short型16位 10 0000 0000 0000 1010 2 左移兩位,右補0 0000 0000 0010 1000 401 先求出 10以補碼的形式...

按位取反符號的介紹

前言 是我最近做面試題的時候遇到的符號,我不知道是什麼含義,上網上查詢之後才知道,下面我通過例題來說明這個符號使用之後的結果是什麼 例題 public class test what is the decimal value fo j at line5?a 0b 1 c 14 d 15 e an e...

關於為什麼負數的補碼為符號位不變各位取反加1

數在計算機中是以二進位制形式表示的。數分為有符號數和無符號數。原碼 反碼 補碼都是有符號定點數的表示方法。乙個有符號定點數的最高位為符號位,0是正,1是副。以下都以8位整數為例,原碼就是這個數本身的二進位制形式。例如0000001 就是 1 1000001 就是 1 正數的反碼和補碼都是和原碼相同。...