zoukankan      html  css  js  c++  java
  • Java 位运算

    Java使用补码来表示二进制数, 在计算机运算的时候, 都是以补码的方式来运算。在补码表示中,最高位为符号位,正数的符号位为0,负数为1。补码的规定如下:
      · 对正数来说,最高位为0,其余各位代表数值本身(以二进制表示)。正数的原码、反码、补码都一样。
      · 对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。以下是-1补码的计算过程:

      10000000000000000000000000000001 (-1的原码)
      11111111111111111111111111111110 (-1的反码:原码除符号位按位取反)
      11111111111111111111111111111111 (-1的补码:反码加1)

    一、位运算的概念

      位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算。

      位运算符可以分为逻辑运算符(包括~、&、|和^)及移位运算符(包括>>、<<和>>>)。

        &(与):当两边操作数的位同时为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++没有的。

      位运算符的优先级:~的优先级最高,其次是<<、>>和>>>,再次是&,然后是^,优先级最低的是|。

    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(" ");
            }
        }
    }

    运行结果

     

    二、位运算的应用

    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

  • 相关阅读:
    jmeter的插件安装
    linux下性能监控工具nmon的使用
    kafka如何保证不重复消费又不丢失数据_Kafka写入的数据如何保证不丢失?
    Goroutine和Panic
    go 并发有趣现象和要避开的坑
    Go语言宕机恢复(recover)——防止程序崩溃
    invalid character 'è' looking for beginning of value
    golang实现RPC的几种方式
    channl与select
    我要在栈上。不,你应该在堆上
  • 原文地址:https://www.cnblogs.com/anxiao/p/6756605.html
Copyright © 2011-2022 走看看