位运算是直接对整数在内存中的二进制位进行操作。
阅读本章时,可以打开计算机上的计算器,并将其设置为程序员模式。
了解位
在计算机内部,数据以二进制来存储,每一个二进制数称为一个位(Bit)。
位运算
位运算通常有如下几个操作:
- 位与(&, and),当两位同时为 1 时才返回 1。
- 位或(|, or),只要有一位为 1 就返回 1。
- 异或(^, xor),当两位相同时返回 0,不相同时返回 1。
- 位非(~, not),将操作数的每个位(包括符号位)全部取反。
- 左移(<<, lsh)
- 右移(>>, rsh)
其中,Java 语言还多一个无符号右移(>>>)。
位与、位或、异或的运算法则如下:
操作数 1 | 0 | 0 | 1 | 1 |
操作数 2 | 0 | 1 | 0 | 1 |
位与 | 0 | 0 | 0 | 1 |
位或 | 0 | 1 | 1 | 1 |
异或 | 0 | 1 | 1 | 0 |
位与
举个例子,5 & 9 = 1
,为什么呢?
首先将这两个数转换成二进制
1 2 3 4
| 5: 0000 0000 0000 0000 0000 0000 0000 0101 9: 0000 0000 0000 0000 0000 0000 0000 1001 ------------------------------------------ &: 0000 0000 0000 0000 0000 0000 0000 0001 = 1
|
位或
5 | 9 = 13
1 2 3 4
| 5: 0000 0000 0000 0000 0000 0000 0000 0101 9: 0000 0000 0000 0000 0000 0000 0000 1001 ------------------------------------------ |: 0000 0000 0000 0000 0000 0000 0000 1101 = 13
|
异或
5 ^ 9 = 12
1 2 3 4
| 5: 0000 0000 0000 0000 0000 0000 0000 0101 9: 0000 0000 0000 0000 0000 0000 0000 1001 ------------------------------------------ ^: 0000 0000 0000 0000 0000 0000 0000 1100 = 12
|
位非
~-5 = 4
1 2
| -5: 1111 1111 1111 1111 1111 1111 1111 1011 (计算机内部负数以补码形式表示) ~-5: 0000 0000 0000 0000 0000 0000 0000 0100
|
左移
左移是将操作数二进制码整体向左移动制定的位数,左移后右边空出来的地方用 0
来填充。
5<<2 = 20
,-5<<2 = -20
1 2 3 4 5 6 7
| 5: 0000 0000 0000 0000 0000 0000 0000 0101 5<<2: 00 0000 0000 0000 0000 0000 0000 0001 0100 -> 0000 0000 0000 0000 0000 0000 0001 0100 = 20 -------------------------------------------------------- -5: 1111 1111 1111 1111 1111 1111 1111 1011 -5<<2: 11 1111 1111 1111 1111 1111 1111 1110 1100 -> 1111 1111 1111 1111 1111 1111 1110 1100 = -20
|
右移
右移是将操作数的二进制码向右移动指定位数,右移后左边空出来的地方以原来的符号为来填充。若原来为正数,则在左边补 0,若为负数,则补 1。
5>>2 = 1
,-5>>2 = -2
1 2 3 4 5 6 7
| 5: 0000 0000 0000 0000 0000 0000 0000 0101 5>>2: 00 0000 0000 0000 0000 0000 0000 0001 01 -> 0000 0000 0000 0000 0000 0000 0000 0001 = 1 ------------------------------------------------------ -5: 1111 1111 1111 1111 1111 1111 1111 1011 -5>>2: 11 1111 1111 1111 1111 1111 1111 1110 11 -> 1111 1111 1111 1111 1111 1111 1111 1110 = -2
|
Java 中的无符号右移
与右移不同,无符号右移无论操作数为正数还是负数都将在左侧补 0。
-5>>>2 = 1073741822
1 2 3
| -5: 1111 1111 1111 1111 1111 1111 1111 1011 -5>>>2: 11 1111 1111 1111 1111 1111 1111 1110 11 -> 0011 1111 1111 1111 1111 1111 1111 1110 = 1073741822
|
参考资料