1. 程式人生 > >Java 位運算符

Java 位運算符

直接 移位 value obi ash 沒有 AI 問題 oid

前言

最近在看hashMap的源碼,看到了一些位運算符,決定深入研究學習一下位運算符。

位運算

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

位運算符

Java中的位運算符一共有:&、|、^ 、<<、>>、>>>、~這7種

1.&(與)、|(或)、^(異或)

public static void main(String[] args) {
        
        int a = 10;
        System.out.println("a的二進制表示:" + Integer.toBinaryString(a));
        
int b = 11; System.out.println("b的二進制表示:" + Integer.toBinaryString(b)); int i = a & b; System.out.println("a & b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); i = a | b; System.out.println("a | b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); i
= a ^ b; System.out.println("a ^ b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); }

運行結果

a的二進制表示:1010
b的二進制表示:1011
a & b = 10,i的二進制表示:1010
a | b = 11,i的二進制表示:1011
a ^ b = 1,i的二進制表示:1

可以通過Java中Integer類自帶將int轉為二進制表示的方法查看二進制

這裏a ^ b 的二進制表示可以看成0001

可以看出

& (與):當a和b二進制表示上相同位數都為1時,i的對應位數上的值才為1(既11-->1 10 -->0 01-->0 00-->0),不難看出 i <= min(a,b)

| (或):當a和b二進制表示上相同位數都為0時,i的對應位數上的值才為0(既11-->1 10 -->1 01-->1 00-->0),不難看出 i >= max(a,b)

^(異或):當a和b二進制表示上相同位數相同時,i的對應位數上的紙值為0(既11-->0 10 -->1 01-->1 00-->0)

2. <<(左移)、>>(帶符號右移)、>>>(無符號右移)

public static void main(String[] args) {
        int i = 1 << 2;
        System.out.println("1 << 2 = " + i);
        i = 1 << 30;
        System.out.println("1 << 30 = " + i);
        i = 1 << 31;
        System.out.println("1 << 31 = " + i);
        i = 1 >> 1;
        System.out.println("1 >> 1 = " + i);
        i = 1 >> 32;
        System.out.println("1 >> 32 = " + i);
        i = -1 >> 1;
        System.out.println("-1 >> 1 = " + i);
        i = -1 >>> 1;
        System.out.println("-1 >>> 1 = " + i);
    }

運行結果

1 << 2 = 4
1 << 30 = 1073741824
1 << 31 = -2147483648
1 >> 1 = 0
1 >> 32 = 1
-1 >> 1 = -1
-1 >>> 1 = 2147483647

一般情況下

a << n = (a * (2的n次方 ))

a >> n=(a-a%2)/(2的n次方)

但是,可以看到上面的例子中可以列出不少返例

這其中主要因為Java中int的範圍

首先,Java中int的範圍是 -2的32次~2的32次-1

另外,我們有沒有考慮過i的邊界問題,當i = 2的32次-1後,再+1,會出現什麽後果?

public static void main(String[] args) {
  int i = Integer.MAX_VALUE +1;
  System.out.println(i);
  System.out.println(Integer.toBinaryString(i));
}

運行結果

-2147483648(-2的32次方。int的最小值)
10000000000000000000000000000000

我們知道int的長度是32位的,要表示Int的正負,Java中的做法是在第32位上做標記,第32位=0時,int為正數,第32位=-1時,int為負數

所以

二進制:00000000000000000000000000000000 ,代表最小的正數0

二進制:10000000000000000000000000000000 ,代表最小的負數-2147483648

從二進制計算的角度不難理解,Integer.MAX_VALUE+1 = Integer.MIN_VALUE

這就是為什麽 1<<31 = -2147483648

我們再來看

1 >> 1 = 0 和 1 >> 32 = 1

這裏我理解為 二進制中移位運算實際是對一個長度為63的二進制數進行操作,其中連續的32位表示int的值,剩余部分全部為0。

然後再講這整個63位的二進制數看成一個圓(循環隊列)

所以,無論一個數左移或者右移32位,始終是這個數本身。

然後,我們來看一下 -1 >>1 = -1 和 -1>>>1 = 2147483647

先從字面上理解,>> 帶符號右移,>>>無符號右移

再進一步解釋就很容易了,63位長度的二進制數中,其中連續的32位表示int的值,剩余的31位再做>>操作時,保持與int的符號相同的值(即int位負,其余31位都為1,int為正,其余31位都為0)

而>>>無符號右移,則是無論int為何,其余31位全部為0

3.~(取反)

    public static void main(String[] args) {
        int i = 10;
        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(~i));
    }

運行結果

1010
11111111111111111111111111110101

取反很容易理解,將0替換成1,將1替換成0

將10的二進制表示補充至完整的32位

00000000000000000000000000001010 取反則等於11111111111111111111111111110101

可以看出 i + ~i = -1

---------------------------------------------------------------------------------------------------------------------

第一次寫博客,很多地方都是個人理解,如果寫得不對的地方,請撥冗指正,謝謝!

Java 位運算符