位運算及原碼、反碼、補碼

位運算

程序中的所有數在計算機內存中都是以二進制的形式儲存的,位運算就是直接對整數在內存中的二進制位進行操作

位運算是更底層一些的操作,位運算通常相比其他運算有着更高的效率

運算符號

含義 C\C++ Java
按位與(AND) a & b a & b
按位或 a | b a | b
按位異或 a ^ b a ^ b
按位取反 ~ a ~ a
左移 a << b a << b
右移 a >> b a >> b
無符號右移 a >>> b

按位與(AND)

按位與處理兩個長度相同的二進制數,兩個相應的二進位都爲1,該位的結果值才爲1,否則爲0。例如:

    0101(十進制5)
AND 0011(十進制3)
  = 0001(十進制1)

按位或(OR)

按位或處理兩個長度相同的二進制數,兩個相應的二進位中只要有一個爲1,該位的結果值爲1。例如:

   0101(十進制5)
OR 0011(十進制3)
 = 0111(十進制7)

按位異或(XOR)

按位異或運算,對等長二進制模式按位或二進制數的每一位執行邏輯按位異或操作。
操作的結果是如果某位不同則該位爲1,否則該位爲0。例如:

    0101(十進制5)
XOR 0011(十進制3)
  = 0110(十進制6)

取反(NOT)

取反是一元運算符,對一個二進制數的每一位執行邏輯反操作。使數字1成爲0,0成爲1。例如:

NOT 0111(十進制7)
  = 1000(十進制8)

左移

左操作數按位左移右操作數指定的位數,移位後空缺的部分全部填0。

    0001(十進制1)
<<     3(左移3位)
  = 1000(十進制8)

右移

左操作數按位右移右操作數指定的位數,左邊的用原有標誌位補充,右邊超出的部分捨棄。

      1010(十進制10)
 >>      2(右移2位)
    = 0010(十進制2)
無符號右移

相比 C、C++、JAVA中有一個特有的無符號右移操作符“>>>”,此操作將忽略操作數的符號 同樣的還有>>>=。

按位右移補零操作符。左操作數的值按右操作數指定的位數右移,左邊部分總是以0填充,右邊超出的部分捨棄。

int a = -8;
int b = a >> 3;
int c = a >>> 3;

結果:
a -8         11111111111111111111111111111000
b -1         11111111111111111111111111111111
c 536870911     11111111111111111111111111111

解讀

計算機中所有數都是以補碼形式存儲的(正數的補碼是本身)。

原碼:10進制轉換成2進制是原碼

反碼: 正數的反碼是本身,負數的反碼是負數的原碼0變爲1,1變爲0 (負數求反碼時候的符號位不參與變換)

補碼: 正數的補碼是本身,負數的補碼就是負數的反碼加一

總結: 正數的原碼,反碼 ,補碼三值合一, 負數的原碼,反碼,補碼不同。

-8
原碼 1000 0000 0000 0000 0000 0000 0000 1000
​反碼 1111 1111 1111 1111 1111 1111 1111 0111
補碼 1111 1111 1111 1111 1111 1111 1111 1000

帶符號右移(左邊的用原有標誌位補充,右邊超出的部分捨棄),即

1111 1111 1111 1111 1111 1111 1111 1000 變成:
1111 1111 1111 1111 1111 1111 1111 1111

補碼 1111 1111 1111 1111 1111 1111 1111 1111
反碼 1111 1111 1111 1111 1111 1111 1111 1110
原碼 1000 0000 0000 0000 0000 0000 0000 0001 轉化爲十進制也就是 -1

無符號右移(左邊部分總是以0填充,右邊超出的部分捨棄),即

1111 1111 1111 1111 1111 1111 1111 1000 變成:
0001 1111 1111 1111 1111 1111 1111 1111

補碼 0001 1111 1111 1111 1111 1111 1111 1111 (正數的原碼,反碼 ,補碼三值合一)
反碼 0001 1111 1111 1111 1111 1111 1111 1111 (正數的原碼,反碼 ,補碼三值合一)
原碼 0001 1111 1111 1111 1111 1111 1111 1111 轉化爲十進制也就是 53687091

擴展爲什麼1字節表示的範圍是[-128,127]

一個字節8位,即可表示2^8 =256,有符號數那就可以表示2^7 =128個正數、2^7 =128個負數了,但是1000 0000和0000 0000其實都是0,所以理論上它只能表示[-127, 127]。
如果計算機用原碼或者反碼,會多佔用一個表達(+0、-0都會有各自的原碼和反碼)。但計算機中使用的是補碼,+0、和-0的補碼都是0000 0000,所以1000 0000可以用來多表達一個數,用來表示-128最合理。
還可以從另外一個角度來理解: -127 的補碼是1000 0001.再減去1 就是1000 0000 。那-127-1=-128。
總結:補碼不僅解決了符號的表示的問題,還統一了符號位和數值位,使得符號位可以和數值位一起直接參與運算。

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