最近看 JDK 的源码, 看到一些 按位运算(Bitwise Operators), 这里做个总结.
1 按位运算符汇总| Operator | Description |
|---|---|
| & | Bitwise AND(按位与) |
| | | Bitwise OR(按位或) |
| ^ | Bitwise XOR(eXclusive OR, 按位异或) |
| ~ | Bitwise Complement(按位取反) |
| << | Left Shift(左移) |
| >> | Signed Right Shift(有符号右移) |
| >>> | Unsigned Right Shift(无符号右移) |
备注:
有符号右移: 右移时不移的符号位.
无符号右移: 右移时移动符号位. (可以理解为 把符号位当做普通的二进制位)
对于正数来说, 有符号右移 和 无符号右移 没有区别, 因为在右移完事了, 左边都要用 0 补齐.
左移: 也会 把符号位当做普通的二进制位.
优先级:
| 运算符 | 综合性 |
|---|---|
| ~ | 从右向左 |
| << >> >>> | 从左向右 |
| & | 从左向右 |
| ^ | 从左向右 |
| | | 从左向右 |
| =(赋值运算符) | 从右向左 |
2 按位与 &
按位与, 两位都为1结果才为1(全1则1):
| x | y | x&y |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
例如:
3 & 5 结果为 1.
(decimal) (binary)
3 = 011
5 = 101
------------------ 按位与(&)
1 = 001
3 按位或 |
按位或, 有1位为1结果就为1(有1则1):
| x | y | x|y |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
例如:
3 | 5 结果为 7.
(decimal) (binary)
3 = 011
5 = 101
------------------ 按位或(|)
7 = 111
4 异或 ^
异或, 两位不同则为1(相异为1):
| x | y | x^y |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
例如:
3 ^ 5 结果为 6.
(decimal) (binary)
3 = 011
5 = 101
------------------ 异或(^)
6 = 110
5 按位取反 ~
按位取反:
| x | ~x |
|---|---|
| 0 | 1 |
| 1 | 0 |
例如:
~3 结果为 -4.
(decimal) (binary)
3 = 011
------------------ 按位取反(~)
-4 = 100
特别注意:
按位取反 ~ 会改变符号位.
备注:
Java 中, int 占 32位, 第 1 位是 符号位, 其余 31 位是数字的二进制值.
在计算机中整数用 补码 表示.
原码: 符号位 和 数字的二进制表示.
反码: 在 原码 的基础上, 符号位不变, 其余位取反.
补码: 正数的补码就是原码本身, 负数的补码是 反码加1.
(decimal) (binary)
3 = 00000000 00000000 00000000 00000011
~3(补码) = 11111111 11111111 11111111 11111100
~3(原码) = 10000000 00000000 00000000 00000100
10000000 00000000 00000000 00000100 这就是 -4 的原码.
6 左移 <<
左移 会 把符号位当做普通的二进制位.
在左移完事后符号位不变的情况下, x 左移 n 位 相当于 x * 2n.
例如:
3 << 2 结果为 12.
(decimal) (binary)
3 = 0011
------------------ 左移2位(<<), 相当于: 3*(2*2)
12 = 1100
7 有符号右移 >>
有符号右移 不会 把符号位当做普通的二进制位.
对于正数, 有符号右移时, 高位(左边)补0;
对于负数, 有符号右移时, 高位(左边)补1;
例如:
-5 >> 2 结果为 -2.
(decimal) (binary)
-5 = 111111111 11111111 11111111 1111011
------------------ 有符号右移 2位(>>)
-2 = 111111111 11111111 11111111 1111110
5 >> 2 结果为 1.
(decimal) (binary)
5 = 000000000 00000000 00000000 0000101
------------------ 有符号右移 2位(>>) 相当于: 5/(2*2)
1 = 000000000 00000000 00000000 0000001
对于正数, x 有符号右移(>>) n 位 相当于 x / 2n.
8 无符号右移 >>>
无符号右移 会 把符号位当做普通的二进制位.
不论正数还是负数, 无符号右移 >>> 高位(左边) 都补0.
(decimal) (binary)
-5 = 111111111 11111111 11111111 1111011
------------------ 无符号右移 2位(>>>)
结果 = 001111111 11111111 11111111 1111110
9 验证程序
public class TCheck {
public static void main(String[] args) {
int a = 0xf; // 15
printBinaryBeauty(a);
System.out.println("=====0====");
printBinaryBeauty(1 << 2); // 000000000 00000000 00000000 0000100
printBinaryBeauty(1 << 3); // 000000000 00000000 00000000 0001000
System.out.println("=====1====");
printBinaryBeauty(1 << 31); // 100000000 00000000 00000000 0000000
printBinaryBeauty(~(1 << 31)); // 011111111 11111111 11111111 1111111
System.out.println("=====2====");
printBinaryBeauty(-5); // 111111111 11111111 11111111 1111011
printBinaryBeauty(-5 >> 2); // 111111111 11111111 11111111 1111110
printBinaryBeauty(-5 >>> 2);// 001111111 11111111 11111111 1111110
System.out.println("=====3====");
printBinaryBeauty(5); // 000000000 00000000 00000000 0000101
printBinaryBeauty(5 >> 2); // 000000000 00000000 00000000 0000001
printBinaryBeauty(5 >>> 2); // 000000000 00000000 00000000 0000001
}
public static void printBinaryBeauty(int num) {
System.out.print(num + " 的二进制表示: ");
for (int i = 0; i < 32; i++) {
int bit = (num & (0x80000000 >>> i)) >>> (31 - i);
System.out.print(bit);
if (i != 0 && i % 8 == 0) {
System.out.print(" ");
}
}
System.out.println();
}
}



