位运算详解

一,(&)与,(|)或,(~)非,(^)异或运算

位运算都是针对当前数的二进制数来进行的运算,所以在运算时要用当前数转化为的二进制格式来做分析。由于计算机底层都是用二进制保存数字,所以用位运算可以加快运算速度。下面的二进制为了简便,舍去了前面的0做比较。

  1. (&)与运算
    对于二进制,相同位都为1,结果才为1,否则结果为0。
表达式 二进制数1 二进制数2 结果
2&3 10(2) 11(3) 10(2)
5&3 101(5) 011(3) 001(1)
  1. (|)或运算
    对于二进制,相同位只要有一个为1,那么结果就是1,否则就为0。
    csdn的表格中放(|)会出问题,就用中文来表示了。
表达式 二进制数1 二进制数2 结果
5或7 101(5) 111(7) 111(7)
3或4 011(3) 100(4) 111(7)
  1. (~)非运算
    对于二进制,相同位为0,结果是1,如果位为1,结果是0。
    需要明白一点的是,在计算机中 正数,负数都是通过补码的形式保存的,而正数的补码是其本身的原码,而负数的补码则要根据其绝对值的原码转化为反码,然后通过加1的操作得到补码的。在计算机内部存储中如int和long类型二进制首位为1就代表负数,为0就是正数。(记得这样保存负数的方法是由冯诺依曼提出的。《计算机与人脑》有讲解负数)

可以记一个结果:
正数取反 为取负后减一
负数取反 为取正后减一

表达式 二进制数 结果
~7 00000000000000000000000000111(7) 11111111111111111111111111111000(-8)
~-4 11111111111111111111111111111100(-4) 00000000000000000000000000011(3)
  1. (^)异或运算
    对于二进制,相同位相同则结果为0,不同则结果为1。
表达式 二进制数1 二进制数2 结果
2^3 10(2) 11(3) 01(1)
1&3 01(1) 11(3) 10(2)
4&3 100(4) 011(3) 111(7)

附代码:

        //& 与运算 对于二进制,相同位都为1,结果才为1,否则结果为0
        System.out.println(2&3); // 10  11      10
        System.out.println(5&3); // 101  011     001 //只要一个为0就为0

        //|(或运算) 对于二进制,相同位只要有一个为1,那么结果就是1,否则就为0
        System.out.println(5|7);  // 101  111    010
        System.out.println(3|4);  // 011  100    111

        //~(非运算)
        //对于二进制,相同位为0,结果是1,如果位为1,结果是0
        //正数取反  为对应负数减一
        //负数取反  为对应正数减一
        System.out.println(~7);  //10001000   -8
        System.out.println(Integer.toBinaryString(7)); //查看二进制
        System.out.println(Integer.toBinaryString(-8));
        System.out.println(~-4);
        System.out.println(Integer.toBinaryString(-4)); //查看二进制
        System.out.println(Integer.toBinaryString(3));

        //^ 异或运算符^ (用英文输入法)
        // 对于二进制,相同位相同则结果为0,不同则结果为1
        System.out.println(2^3); // 10  11  --01   第1位相同,第2位不同 保留第2位
        System.out.println(1^3); // 01  11  --10   第2位相同,第1位不同 保留第2位
        System.out.println(3^4); // 011  100  --111

二,位移运算

(为简便部分省去了前面的0或1)

  1. (<<) 向左位移

无论正负数,后面补零。左移多少就补多少个0。结果为乘以2的n次方。

表达式 二进制数 结果
3<<1 00011(3) 00110(6)
3<<2 00011(3) 01100(12)
3<<3 00011(3) 011000(24)
3<<6 00011(3) 011000000(192)
-3<<1 11111111111111111111111111111101(-3) 11111111111111111111111111111010(-6)
  1. (>> ) 向右位移

向右位移,正数前面补零,负数前面补1。结果为除以2的n次方。

表达式 二进制数 结果
12>>1 001100(12) 000110(6)
12>>2 001100(12) 000011(3)
12>>3 001100(12) 000001(1)
-12>>2 1110100(-12) 1111101(-3)
  1. (>>>)无符号右移
    无符号位移,无论正负数,前面补零。正数不影响运算,负数会从最大正数开始递减。
表达式 二进制数 结果
12>>>1 001100(12) 000110(6)
12>>>2 001100(12) 000011(3)
12>>>3 001100(12) 000001(1)
-12>>>2 11111111111111111111111111110100(-12) 00111111111111111111111111111101(1073741821)

附代码参考:

        System.out.println("<< 向左位移 ,无论正负数,后面补零。结果为乘以2的n次方");
        System.out.println("3左移1位:"+(3<<1));    //00011--->00110
        System.out.println("3左移2位:"+(3<<2));    //00011--->001100
        System.out.println("3左移3位:"+(3<<3));   //00011--->011000
        System.out.println("3左移6位:"+(3<<6));   //00011--->11000000
        System.out.println("-3左移1位:"+(-3<<1));
//        System.out.println(Integer.toBinaryString(-3));
//        System.out.println(Integer.toBinaryString(-6));

        System.out.println(" >> 向右位移,正数前面补零,负数前面补1。结果为除以2的n次方");
        System.out.println("12右移1位:"+(12>>1));    //001100--->000110
        System.out.println("12右移2位:"+(12>>2));    //001100--->000011
        System.out.println("12右移3位:"+(12>>3));    //001110--->000001
        System.out.println("-12右移2位:"+(-12>>2));
        System.out.println(Integer.toBinaryString(-12));

        System.out.println(">>>无符号位移,无论正负数,前面补零。正数不影响运算,负数会从最大正数开始递减。");
        System.out.println("12无符号位移1位:"+(12>>>1));    //001100--->000110
        System.out.println("12无符号位移3位:"+(12>>>3));    //001110--->000001
        System.out.println("-12无符号位移2位:"+(-12>>>2));
        System.out.println(Integer.toBinaryString(-12));
        System.out.println(Integer.toBinaryString(1073741821));

查考文章:
JAVA位运算详解 (https://blog.csdn.net/LS1firesoar/article/details/78032303)
java中的(~)运算符原理https://blog.csdn.net/qq_34509230/article/details/79073553

你可能感兴趣的:(java编程设计)