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
}
}
-
- a ^ a =0 (任何数异或本身结果为0)
-
- a ^ b =b ^ a (交换律)
-
- a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c (结合律)
-
- 0 ^ a = a (异或0具有保持的特点)
-
- a ^ b ^ a = b (根据①②④可得)
其他更详尽的应用参考内容:一篇搞定位运算——java位运算详解_java位运算符 算法-CSDN博客