深刻理解位運算操做及使用場景

工做中一直沒用過位操做,只有在閱讀一些源碼的時候會看到使用位運算符(由於直接使用位運算符效率更高),爲了更好的閱讀源碼那就好好學習一下吧,順便把學習的東西記下來!算法

全部的位運算都是在二進制下來進行運算的,再二進制下只有0/1。bash

 

1. ~ 位求反性能

運算符規則是:將運算符後二進制數反轉,0變1,1變 0,因此對一個數取反偶數次結果是它自己。學習

例如:blog

0000 0000 0000 0000 0000 0000 0000 0011 -> 3
1111 1111 1111 1111 1111 1111 1111 1100 -> ~ 3 = -4

經常使用場景:源碼

求相反數: ~a + 1table


2. << 左移class

運算符規則是:各二進位所有左移若干位,高位丟棄,低位補0。效率

例如:6 << 2 = 24變量

0000 0000 0000 0000 0000 0000 0000 0110 -> 6
0000 0000 0000 0000 0000 0000 0001 1000 -> 6 << 2 = 24

咱們將6的二進位向左移動兩位,低位補上兩個0,高位丟棄,得出來的結果就是24。

經常使用場景:

左移常被用來作 * (2 ^ n)的運算,由於直接基於二進制運算,因此左移效率比 * (2 ^ n)高。


3. >> 右移

運算符規則是:各二進位所有右移若干位,正數高位補0,負數高位補1,低位丟棄。

例如: 12 >> 2 = 3

0000 0000 0000 0000 0000 0000 0000 1100     -> 12
0000 0000 0000 0000 0000 0000 0000 0011     -> 12 >> 2 = 3

由於12是正數,右移過程當中高位補上兩個0,低位丟棄,得出來的結果就是3。
例如:-12 >> 2 = -3

1111 1111 1111 1111 1111 1111 1111 0100    -> -12
1111 1111 1111 1111 1111 1111 1111 1101    -> -12 >> 2 = -3

由於-12是負數,右移過程當中高位補上兩個1,低位丟棄,得出來的結果就是-3。

經常使用場景:

右移常被用來作 / (2 ^ n)的運算,由於直接基於二進制運算,因此右移效率比 / (2 ^ n)高。


4. >>> 無符號右移

運算符規則是:各二進位所有右移若干位,高位補0,低位丟棄。

例如: 12 >>> 2 = 3

0000 0000 0000 0000 0000 0000 0000 1100     -> 12
0000 0000 0000 0000 0000 0000 0000 0011     -> 12 >>> 2 = 3

咱們將12的二進位向右移動兩位,高位補上兩個0,低位丟棄,得出來的結果就是24。
例如:-12 >>> 2 = 1073741821

1111 1111 1111 1111 1111 1111 1111 0100    -> -12
0011 1111 1111 1111 1111 1111 1111 1101    -> -12 >> 2 = 1073741821

咱們將-12的二進位向右移動兩位,高位補上兩個0,低位丟棄,得出來的結果就是1073741821。

 

5. & 位與
運算符規則是:運算符兩邊有0,結果就爲0 ,只有當兩邊同時爲1是,結果才爲1。

以下:

 0 & 0 = 0;     0 & 1 = 0;     1 & 0 = 0;       1 & 1= 1;

例如:3&5  

0000 0000 0000 0000 0000 0000 0000 0011 -> 3
0000 0000 0000 0000 0000 0000 0000 0101 -> 5
0000 0000 0000 0000 0000 0000 0000 0001 -> 3 & 5 = 1

位與運算的特殊用途:

1.清零(將一個單元與0進行位與運算結果爲零)
2.取一個數指定位(例如取num=1010 1101的低四位 則將num&0xF獲得0000 1101)。
3.判斷奇偶性:用if ((a & 1) == 0) 代替 if (a % 2 == 0)來判斷a是否是偶數。


6. | 位或
運算規則就是 運算符兩邊有1,結果就爲1 ,只有當兩邊同時爲0是,結果才爲0。

以下:

0 | 0 = 0;  0 | 1 = 1;  1 | 0 = 1;   1 | 1 = 1 ;

例如:3|5 

0000 0000 0000 0000 0000 0000 0000 0011 -> 3
0000 0000 0000 0000 0000 0000 0000 0101 -> 5
0000 0000 0000 0000 0000 0000 0000 0111 -> 3 | 5 = 7

另,負數按補碼形式參加按位或運算。

使用場景:

下面這個方法是摘自HashMap類,這個算法來修改用戶使用構造器傳進來的size的,這個算法是使用移位和或結合來實現的,性能上比循環判斷要好。

public static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

 

7. ^ 位異或
運算規則是:當運算符兩邊相同位置都是相同,結果返回0,不相同時返回1。

例如:3 ^ 5 = 1

0000 0000 0000 0000 0000 0000 0000 0011 -> 3
0000 0000 0000 0000 0000 0000 0000 0101 -> 5
0000 0000 0000 0000 0000 0000 0000 0110 -> 3 ^ 5 = 6

一般咱們交換兩個數會使用一個臨時變量來幫忙:

int t = a;
a = b;
b = t;

使用 ^ 位運算符(裝逼必備)

a ^= b;
b ^= a;
a ^= b;
相關文章
相關標籤/搜索