天天看點

按位邏輯操作符那些事兒按位操作符運算符概述

title: 按位邏輯操作符那些事兒

date: 2017-02-24

tag: java

按位操作符運算符概述

在java底層裡面,用到了很多這種符号,不對這些按位邏輯符号弄清楚,不容易看懂jdk源碼,這裡對按位符号做一個簡單的梳理

運算符 用法 描述
按位與( AND)

a & b

對于每一個比特位,隻有兩個操作數相應的比特位都是1時,結果才為1,否則為0。
按位或(OR)

a | b

對于每一個比特位,當兩個操作數相應的比特位至少有一個1時,結果為1,否則為0。
按位異或(XOR)

a ^ b

對于每一個比特位,當兩個操作數相應的比特位有且隻有一個1時,結果為1,否則為0。
按位非(NOT)

~ a

反轉操作數的比特位,即0變成1,1變成0。
左移(L)

a << b

a

的二進制形式向左移

b

(< 32) 比特位,右邊用0填充。
有符号右移

a >> b

将 a 的二進制表示向右移

b

(< 32) 位,丢棄被移出的位。
無符号右移

a >>> b

将 a 的二進制表示向右移

b

(< 32) 位,丢棄被移出的位,并使用 0 在左側填充。

這裡注意,java裡面沒有無符号左移,因為無符号左移<<<和左移<<是一樣的概念

按位邏輯操作符

& (按位與)

對每對比特位執行與(AND)操作。隻有 a 和 b 都是 1 時,a AND b 才是 1。與操作的真值表如下:

a b a AND b
1
1
1 1 1

上代碼:

@Test
public void testAnweiyu(){
    //按位與,1與0位0,1與1為1,0與0為0
    int a= & ;
    toBinaryOutPut(,"&",);
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果:
 & 
====
           

| (按位或)

對每一對比特位執行或(OR)操作。如果 a 或 b 為 1,則

a

OR

b

結果為 1。或操作的真值表:

a b a OR b
1 1
1 1
1 1 1
@Test
public void testAnweiHuo(){
    //按位或,1或0為1,0或0為0,1或1為1
    int a= | ;
    toBinaryOutPut(,"|",);
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果
 | 
====
           

^ (按位異或)

對每一對比特位執行異或(XOR)操作。當 a 和 b 不相同時,

a

XOR

b

的結果為 1。異或操作真值表:

a b a XOR b
1 1
1 1
1 1
@Test
    public void testAnweiYiHuo(){
        int a= ^ ;
        toBinaryOutPut(,"^",);
        System.out.println(Integer.toBinaryString(a)+"===="+a);
    }
結果
 ^ 
====
           

~ (按位非)

對每一個比特位執行非(NOT)操作。NOT

a

結果為 a 的反轉(即反碼)。非操作的真值表:

a NOT a
1
1
@Test
public void testAnweiFei(){
    int a=~;
    System.out.println(Integer.toBinaryString());
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果

====-
           

按位移動操作符

<<有符号左移

該操作符會将第一個操作數向左移動指定的位數。向左被移出的位被丢棄,右側用 0 補充

在數字 x 上左移 y 比特得到 x * 2y

上代碼

@Test
public void testLeftMove(){
    int a=<<;//9左移動2位
    toBinaryOutPut(,"<<",);
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果:
 << 
====
           

>>有符号右移

該操作符會将第一個操作數向右移動指定的位數。向右被移出的位被丢棄,拷貝最左側的位以填充左側。由于新的最左側的位總是和以前相同,符号位沒有被改變。是以被稱作“符号傳播”。

例如,

9 >> 2

得到 2

@Test
public void testRightMove(){
    int a=>>;//9右邊移動2位
    toBinaryOutPut(,">>",);
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果:
 >> 
====
           

>>>無符号右移

該操作符會将第一個操作數向右移動指定的位數。向右被移出的位被丢棄,左側用0填充。因為符号位變成了 0,是以結果總是非負的。(譯注:即便右移 0 個比特,結果也是非負的。)

對于非負數,有符号右移和無符号右移總是傳回相同的結果。例如,

9 >>> 2

得到 2 和

9 >> 2

相同

但是對于負數卻不盡相同。

-9 >>> 2

産生 1073741821 這和

-9 >> 2

不同:

上代碼:

@Test
public void testNoSignRightMove(){
    int a=->>>;//9無符号右移動2位
    toBinaryOutPut(-,">>>",);
    System.out.println(Integer.toBinaryString(a)+"===="+a);
}
結果:
 >>> 
====
           

提問時間如下:

  • 首先負數的二進制為什麼是這樣的?

    在計算機中,負數以其正值的補碼形式表達,将二進制數按位取反,所得的新二進制數稱為原二進制數的反碼,然後反碼+1就是補碼了

    例如:9的原碼是00000000 00000000 00000000 00001001

    ​ 反碼是11111111 11111111 11111111 11110110

    ​ 補碼是11111111 11111111 11111111 11110111

    是以-9是這樣的

  • int在計算機中存儲的是4位元組,是以有32位,是以這麼長,前面正數是因為把前面的0省略了
  • 那麼有符号右移和無符号右移有什麼差別呢?
    一個是copy最左側的位來填充,一個是用0來填充,是以無符号右移總是一個正數