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

相关文章
相关标签/搜索