位运算符的分类
1、&
2、|
3、^
4、~
5、<<: 左移
6、>>: 右移
7、>>>: 无符号右移
public class OptWeiDemo1 {
public static void main(String[] args) {
byte a = 3;
byte b = 4;
System.out.println(a&b);//输出结果:0
System.out.println(a|b);//输出结果:7
System.out.println(a^b);//输出结果:7
System.out.println(~a); //输出结果:-4
}
}
下面依次进行分析
分析代码
由于数据在计算机中参与运算的都是补码,而想要知道补码,就得知道反码,原码,就得求出二进制
例如:
3的二进制:00000011
4的二进制:00000100
又由于3和4都是正数
3的补码:00000011
4的补码:00000100
分析System.out.println(a&b);//输出结果:0
& 运算:有0则0
3的补码: 00000011
&
4的补码: 00000100
---------------
00000000
结果是 : 0
System.out.println(a|b);//输出结果:7
| 运算:有1则1
3的补码: 00000011
|
4的补码: 00000100
---------------
00000111
结果是 : 7
System.out.println(a^b);//输出结果:7
^ 运算:相同则0,不同则1
3的补码: 00000011
^
4的补码: 00000100
---------------
00000111
结果是 : 7
System.out.println(~a); //输出结果:-4
~ 运算:1变成0,0变成1
~ 运算:1变成0,0变成1
00000011
~
-------------
补码: 11111100
已知补码求原码:
反码: 11111011
原码: 10000100
结果是:-4
<<(左移)、>>(右移)和>>>(无符号右移)的概念
1、<<: 左移,二进制左移,右边用0补齐,多出来的丢弃
2、 >>: 右移,最左边最高位是0用0补齐,最高位是1就用1补齐,多出来的丢弃。
3、>>>: 无符号右移,无论左边最高是0还是1,都用0补齐,多出来的丢弃。
举例说明:
public class OptWeiDemo2 {
public static void main(String[] args) {
System.out.println(3<<2); //12 = 3*4 = 3*2^2
System.out.println(24>>2); //6 = 24/(2*2)
System.out.println(-24>>2);// -6
System.out.println(-24>>>2);//1073741818
}
}
System.out.println(3<<2); //12 = 3*4 = 3*2^2
<<: 左移,二进制左移,右边用0补齐
3的二进制:00000000 00000000 00000000 00000011
由于3是正数,所以原码,反码,补码都一样
3的补码:00000000 00000000 00000000 00000011
左移:
00000000 00000000 00000000 00000011
(00)00000000 00000000 00000000 00001100 (补码)
由于最高位是0,既是补码也是原码,所以结果是: 12
System.out.println(24>>2); //6 = 24/(2*2)
>>: 右移,最左边最高位是0用0补齐,最高位是1就用1补齐,多出来的丢弃。
24的二进制:00000000 00000000 00000000 00011000
由于24是正数,所以原码,反码,补码都一样
24的补码:00000000 00000000 00000000 00011000
右移:
00000000 00000000 00000000 00011000
0000000000 00000000 00000000 000110(00) (补码)
由于最高位是0,既是补码也是原码,所以结果是:6
System.out.println(-24>>2);// -6
>>: 右移,最左边最高位是0用0补齐,最高位是1就用1补齐,多出来的丢弃。
-24的二进制:10000000 00000000 00000000 00011000
已知原码求补码:
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
右移:
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) (补码)
已知补码求原码:
补码:11111111 11111111 11111111 11111010
反码:11111111 11111111 11111111 11111001
原码:10000000 00000000 00000000 00000110
最终结果是:-6
System.out.println(-24>>>2);//1073741818
>>>: 无符号右移,无论左边最高是0还是1,都用0补齐,多出来的丢弃。
-24的二进制:10000000 00000000 00000000 00011000
已知原码求补码:
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
无符号右移2位:
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00) (补码)
由于最高位是0,所以它的原码,反码,补码都是一样的。
最终结果位:0011111111 11111111 11111111 111010 = 1073741818
关于位运算符的面试题
题目:请用最有效率的方式写出计算2乘以8的结果
public class OptWeiDemo2 {
public static void main(String[] args) {
System.out.println(2<<3); // 2*2^3
}
}
解答:这种方法是最有效率的,因为这是直接用<<(左移位运算符)来计算。