Java 位運算

Java使用補碼來表示二進制數, 在計算機運算的時候, 都是以補碼的方式來運算。在補碼錶示中,最高位爲符號位,正數的符號位爲0,負數爲1。補碼的規定以下:
  · 對正數來講,最高位爲0,其他各位表明數值自己(以二進制表示)。正數的原碼、反碼、補碼都同樣。
  · 對負數而言,把該數絕對值的補碼按位取反,而後對整個數加1,即得該數的補碼。如下是-1補碼的計算過程:
函數

  10000000000000000000000000000001 (-1的原碼)
  11111111111111111111111111111110 (-1的反碼:原碼除符號位按位取反)
  11111111111111111111111111111111 (-1的補碼:反碼加1)spa

1、位運算的概念3d

  位運算表達式由操做數和位運算符組成,實現對整數類型的二進制數進行位運算。code

  位運算符能夠分爲邏輯運算符(包括~、&、|和^)及移位運算符(包括>>、<<和>>>)。對象

    &(與):當兩邊操做數的位同時爲1時,結果爲1,不然爲0。 如1100&1010=1000
    | (或) :當兩邊操做數的位有一邊爲1時,結果爲1,不然爲0。 如1100|1010=1110
    ~(非):0變1,1變0。 如 ~1100=0011
    ^(異或)   :兩邊的位不一樣時,結果爲1,不然爲0。 如1100^1010=0110
    <<(左移):a向左移動b指定的位數(在低位補0)。表示原來的值乘2。(a<<b, a表示運算符左側的運算對象,b表示右側的數值)
    >>(右移):a向右移動b指定的位數。若值爲正,則在高位插入0;若值爲負,則在高位插入1。
    >>>(無符號右移):a向右移動b指定的位數。不管正負,都在高位插入0。這一運算符是C或C++沒有的。blog

  位運算符的優先級:~的優先級最高,其次是<<、>>和>>>,再次是&,而後是^,優先級最低的是|。hash

public class Test {
    
    public static void main(String[] args) {
        Integer a = Integer.MAX_VALUE;
        Integer b = Integer.MIN_VALUE;
        toBinary("(MAX_INT) a", a);
        toBinary("(MIN_INT) b", b);
        toBinary("~ b", ~b);
        toBinary("a & b", a & b);
        toBinary("a | b", a | b);
        toBinary("a ^ b", a ^ b);    
        toBinary("b << 2", b << 2);    
        toBinary("b >> 2", b >> 2);    
        toBinary("b >>> 2", b >>> 2);    
    }
    
    public static void toBinary(String op, Integer a) {
        String str = Integer.toBinaryString(a);
        System.out.printf("%n%11s: ", op);
        for(int i = 0, delta = 32 - str.length(); i < 32; i++){
            if(i < delta)
                System.out.print("0");
            else
                System.out.print(str.charAt(i - delta));
            if((i + 1) % 8 ==0)
                System.out.print(" ");
        }
    }
}

運行結果table

 

2、位運算的應用class

1. m*2^n

  3*2^5 :  (3<<5))變量

  法則一:任何數左移(右移)32的倍數位等於該數自己。

  法則二:在位移運算m<<n的計算中,若n爲正數,則實際移動的位數爲n%32,若n爲負數,則實際移動的位數爲(32+n%32),右移,同理。

2. 判斷一個數n的奇偶性

  n&1 == 1? "奇數" : "偶數"

  int類型的1前31位都是0,最低位爲1,當一個數爲奇數,其最低位也是1。

3. 不用臨時變量交換兩個數

  異或沒有順序性,且知足如下規則:

  ① a ^ a =0
  ② a ^ b =b ^ a
  ③ a ^b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
  ④ d = a ^b ^ c 能夠推出 a = d ^ b ^ c.
  ⑤ a ^ b ^a = b.

  根據第五個規則,能夠交換變量值。

public class Test {
    
    public static void main(String[] args) {
        int a = 4;
        int b = 10;
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println("a=" + a + ", b=" + b);
    }
}

運行結果:        a=10, b=4

計算過程以下:

   a = a ^ b
 b = a ^ b = (a ^ b) ^ b = a
 a = a ^ b = (a ^ b) ^ a = b

 

4. 計算散列碼

   HashMap中在使用put函數插入值,會先計算當前元素的hash值,來計算該元素在hashtable中的存儲位置。

int hash = key.hashCode();
hash ^= (hash >>> 20) ^ (hash >>> 12); 
int h = hash ^ (hash >>> 7) ^ (hash >>> 4); 

  散列的本意就是要儘可能均勻分佈,通過上面的計算,能夠把「1」變的均勻一點:

  before:12539 = 00000000 00000000 00110000 11111011      after:13206 = 00000000 00000000 00110011 10010110

相關文章
相關標籤/搜索