Java位运算符详解

119 阅读5分钟

Java位运算符

目录

int类型是由32位bit组成,这里为了表现方便,将高位0直接删除掉了,在Java中没有无符号右移运算符。

1. & 按位与运算

两个操作数对应位同为1时,结果为1,其余全为0。

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(3&2); //2
    }
}
 011  3
&010  2
 010  2

2. | 按位或运算符

两个操作数对应位只要有一位为1时,结果为1,其余全为0。

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(3|2);  //3
    }
}
 011  3
|010  2
 011  3

3. ~按位取非

如果是0取~就为1,如果是1取~就为0

 public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(~3); //-4
    }
}
 
 0000 0000 0000 0000 0000 0000 0000 0011  3
~1111 1111 1111 1111 1111 1111 1111 1100  -4

解释:因为取非后高位变成了1,表示该数是负数,负数在二进制中通过补码表示,因此需要先对其转换为对应的反码,再计算原码
补码 = 反码+1
补码 1111 1111 1111 1111 1111 1111 1111 1100  
反码 1111 1111 1111 1111 1111 1111 1111 1011
原码 0000 0000 0000 0000 0000 0000 0000 0100 -4

4. ^ 按位异或

当对应bit位不同时时结果取1,否则取0

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(3^2);  //3
    }
}
 011  3
^010  2
 001  1

5. <<左移运算符

符号位不变,低位补0。移几位补几个0。正数或者负数左移,低位都是用0补。

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(3<<2);  //3
    }
}
0 0011    3
0 1100    12

6. >>右移运算符

如果值为正,则在高位补0,如果值为负,则在高位补1

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(-3>>2);  //-1
    }
}

     1111 1111 1111 1111 1111 1111 1111 1101  //-3
>>   1111 1111 1111 1111 1111 1111 1111 1111
反码  1111 1111 1111 1111 1111 1111 1111 1110
原码  0000 0000 0000 0000 0000 0000 0000 0001  //-1

7. >>>无符号右移

无论数值正负,均会使用0填充高位

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(-3>>>2);
    }
}

    1111 1111 1111 1111 1111 1111 1111 1101  //-3
>>> 0011 1111 1111 1111 1111 1111 1111 1111  //1073741823


8. 位运算符的应用

8.1. m<<n = m*2^n

法则一:任何数左移(右移)32的倍数位等于该数本身。在Java中int类型使用32的倍数位移,无论是左移还是右移,都相当于将整个数值的二进制表示循环移动了一整轮。

法则二:在位移运算m<<n的计算中,若n为正数,则实际移动的位数为n%32,若n为负数,则实际移动的位数为(32+n%32),右移,同理。

public strictfp class  Main {
    public static void main(String[] args) {
        System.out.println(8>>2);
    }
}

左移是乘以2的n次幂,右移是除以2的n次幂,hashmap中扩容有对应的使用。

8.2. 判断一个数是否是偶数

n&1 == 1?”奇数”:”偶数”,分析:因为对于二进制计算来说只有首位2的0次方计算出来时奇数,其他位置计算出来均为偶数,由于偶数+奇数 = 奇数,因此对于奇数来说,第一个bit位一定是1。又因为&只有两个比特位均为1才返回1,因此实际相当于比较第一个bit位,因此可以拿来判断奇数和偶数;

8.3. 不用临时变量交换两个数的值

public strictfp class  Main {
    public static void main(String[] args) {
        int n = 2;
        int m = 3;
        n = n ^ m;
        m = m ^ n; // m^n=m^(n^m)=m^(m^n)=n
        n = n ^ m; // n^m=n^(m^n)=n^(n^m)=m
    }
}

    1. a ^ a =0 (任何数异或本身结果为0)
    1. a ^ b =b ^ a (交换律)
    1. a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c (结合律)
    1. 0 ^ a = a (异或0具有保持的特点)
    1. a ^ b ^ a = b (根据①②④可得)

其他更详尽的应用参考内容:一篇搞定位运算——java位运算详解_java位运算符 算法-CSDN博客