天天看點

Java位運算之異或運算,非運算,與運算,或運算,移位運算

java語言對應數學中邏輯運算

"∧" 表示 "與" 對應java : &

"∨" 表示 "或" 對應java : |

"┐"表示 "非" 對應java : ~

a⊕b = (¬a ∧ b) ∨ (a ∧¬b) 異或(xor) 對應java : ^

在計算機中,數值一直以補碼存儲,運算也用補碼。

ex:8bit signed int (-128~127),最高位為符号位,0000 0000 ~ 1111 1111 以補碼形式存儲 帶符号數

0000 0000 :十進制0 1+(-1)=0,其實用的是1的補碼和-1的補碼相加。正數的補碼為本身

0000 0001 :1(0+1) 即0000s 00001+?= 0000 0000 當?為1111 1111 時相加為1 0000 0000 最高位進位被舍棄

.... 由此誕生了-1在計算機中存儲的二進制 1111 1111,即-1的補碼

0111 1111 : 127 所有從 1~127 都有對應的-1~-127,一個數的補碼+該數相反數的補碼 = 0(1 0000 0000)

1000 0000 : -128 多出了 0000 0000 (0的補碼)和 1000 0000 (-128的補碼)

....

1111 1111 : -1 從-128(1000 0000)+1.... -1(11111 1111))+1 = 0 (0000 0000) +1.... 127 (0111 111)

驗證計算機隻會做加法,且帶符号位(8 bit)整型範圍(-128 ~127)

同時可以證明 負數的補碼=相反數的補碼按位取反+1

正數原碼=補碼=反碼,涉及負數才有補碼反碼之間計算

原碼:1010(-2)

補碼:1110

補碼 = (原碼)按位取反+1(原碼除符号位按位取反+1)

在位運算中計算得知補碼後怎麼轉換為直覺的原碼

原碼 = (補碼 -1)後除符号位按位取反

原碼 = 反碼(補碼除符号位取反) +1

Java中沒有無符号資料類型,取最高位作為符号位表示正負數,但運算和位操作都使用補碼計算

與運算 &  規則 :對應數的補碼對應位都為1時結果位才為1

System.out.println( 7 & 9);//result為1

分析:

7的二進制:0111(即為源碼也為補碼)

9的二進制:1001

result :0001

System.out.println(-1&-2); //輸出-2

分析:

-1原碼:1001 對應補碼:1111

-2原碼:1010 對應補碼:1110

result: 得到補碼:1110(即負數補碼,-2的補碼)

1101 補碼-1 或 1001 除符号位按位取反得反碼

1010 按位取反得原碼,即帶符号的-2 1010 反碼+1得原碼 -2

同理或運算,異或運算,取反運算相同,都為對補碼行運算

輸出結果

或運算 | 規則:有一個位為1,則結果位為1

 System.out.println(7 | 9);// 15

分析:

7的二進制:0111

9的二進制:1001

result :1111

異或運算  ^ 規則:對補碼不同位不同為1 

System.out.println( 7 & 9);//result為14//System.out.println((~7&9)|(7&~9));//結果相同

分析:

7的二進制:0111

9的二進制:1001

result :1110

取反運算 ~ 規則:對補碼按位取反

System.out.println( ~7);//輸出-8

分析:

7的二進制:0000 0000 0000 0000 0000 0000 0000 0111

正整數的原碼=補碼,然後對補碼求反

result: 1111 1111 1111 1111 1111 1111 1111 1000  //符号位改變(第一位),取反之後變成負數了(即負數的補碼)

1000 0000 0000 0000 0000 0000 0000 0111 //反碼(除符号位取反)

1000 0000 0000 0000 0000 0000 0000 1000 //對反碼+1(得原碼)== -8

System.out.println( ~-7);//輸出6

分析:

-7的二進制:1000 0000 0000 0000 0000 0000 0000 0111 //該為原碼,計算機中存儲,計算的為補碼,需轉換為補碼再按位求反

result: 1111 1111 1111 1111 1111 1111 1111 1001  //補碼

0000 0000 0000 0000 0000 0000 0000 0110 //對補碼求反仍然為補碼

// 但符号位為0 即正數,補碼=原碼  == 6

移位運算 << (有符号左移), >>(有符号右移) , >>>(無符号右移)

<< :左移後,低位補0

>> :右移後,正數高位補0,負數高位補1

>>> :無符号右移,高位都補0

a << n  左移n位,值為a*2^n

a >> n  右移n位,值為a/2^n

繼續閱讀