一、 常见位运算符
运算符 | 运算 | 范例 |
---|---|---|
<< | 左移 | 3 << 2 = 12 -> 3 * 2 * 2 = 12 |
>> | 右移 | 3 >> 1 = 1 -> 3 / 2 = 1 |
>>> | 无符号右移 | 3 >>> 1 = -1 -> 3/2 = 1 |
& | 与运算 | 6 & 3 = 2 |
| | 或运算 | 6 | 3 = 7 |
^ | 异或运算 | 6 ^ 3 = 5 |
~ | 取反运算 | ~6 = -7 |
- 位运算是直接对整数的二进制进行的运算
- 没有<<< 无符号左移
二、左移举例
21(十进制整数)
21 << 2 = ?
首先将21转换位二进制
10101 向左移两位,空出位置补0 于是变成了
1010100 转为十进制:1 * 22 + 1 * 24 + 1 * 26 = 84
所以 21 << 2 = 84
总结:每向左移一位相当于在原来数上的基础乘以2,即 21 * 2n,n为向左移位数
举例说明:
10101 = 1 * 20 + 1 * 22 + 1 * 24
-
左移一位实际上为 1 * 21 * (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 * 21 = 21 * 2 = 42
等同于1 * 2 * (1 * 20 + 1 * 22 + 1 * 24 ) => 21 * 2 = 21 * 2 = 42
-
左移两位实际上为 1 * 22 * (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 * 22 = 21 * 4 = 84
等同于 1 * 2 * 2 * (1 * 20 + 1 * 22 + 1 * 24 ) => 21 * 2 * 2 => 21 * 4 = 84
-
左移三位实际上为 1 * 23 * (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 * 23 = 21 * 8 = 168
等同于 1 * 2 * 2 *2 * (1 * 20 + 1 * 22 + 1 * 24 ) => 21 * 2 * 2 * 2=> 21 * 8 = 168
三、右移举例
21(十进制整数)
21 >> 2 = ?
首先将21转换位二进制
10101向右移两位,前方位置补零于是变成了
00101 转为十进制:1 * 20 + 1 * 22= 5
所以 21 >> 2 = 5
总结:每向右移一位相当于在原来数上的基础除以2,即 21 / 2n,n为向右移位数
推导过程:
10101 = 1 * 20 + 1 * 22 + 1 * 24
-
右移一位实际上为 (1 * 21 ) / (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 / 21 = 21 / 2 = 10
等同于(1 * 2) / (1 * 20 + 1 * 22 + 1 * 24 ) => 21 / 2 = 21 / 2 = 10
-
左移两位实际上为 (1 * 22) / (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 / 22 = 21 / 4 = 5
等同于 (1 * 2 * 2) / (1 * 20 + 1 * 22 + 1 * 24 ) => 21 / (2 * 2) => 21 / 4 = 5
-
左移三位实际上为 (1 * 23) / (1 * 20 + 1 * 22 + 1 * 24 )
转换为十进制的乘法即为 21 / 23 = 21 / 8 = 2
等同于 (1 * 2 * 2 *2) / (1 * 20 + 1 * 22 + 1 * 24 ) => 21 / (2 * 2 * 2)=> 21 / 8 = 2
四、总结
位运算符的效率高于算术运算符。
经典面试题:
最高效的方式计算 2 * 8 ?
答: 2 << 3 或 8 << 1
五、位运算符的细节
<< | 空位补0,被移除的高位丢弃,空缺为补0 |
---|---|
>> | 被移位的二进制位是0,右移后,空缺位0;最高位是1,空缺为补1。 |
>>> | 被移位二进制最高位无论是0或者是1,空缺位都用0补。 |
& | 二进制位进行&运算,只有 1 & 1时结果是1,否则是0; |
| | 二进制位进行 | 运算,只有 0 | 0 时结果是0,否则是1; |
^ | 相同的二进制位进行^运算,结果是0;1 ^ 1 = 0 ,0 ^ 0 = 0 不相同的二进制位 ^ 运算结果是1。1 ^ 0 = 1 ,0 ^ 1 = 1 |
~ | 正数取反,各二进制码按补码各位取反;负数取反,各二进制码按补码各位取反 |
六、其他运算符的举例
6.1 &(与)运算符
12 & 5 = 4
过程
12 => 1100(二进制)
5 => 0101(二进制)
比较过程:
0 & 1 = 0; 0 & 0 = 0 ; 1 & 1 = 1; 1 & 0 = 0
结果为 0100(二进制) => 4 (十进制)
总结:只有当比较双方都为1时,结果才为1,,否则为0
6.2 |(或)运算符
12 | 5 = 4
过程
12 => 1100(二进制)
5 => 0101(二进制)
比较过程:
0 | 1 = 1; 0 & 0 = 0 ; 1 & 1 = 1; 1 & 0 = 1
结果为: 1101(二进制) => 13(十进制)
总结:当比较双方只要有一个为1,那么其值为1,否则为0
6.3 ^(异或)运算符
12 ^ 5 = 4
过程
12 => 1100(二进制)
5 => 0101(二进制)
比较过程:
0 ^ 1 = 1; 0 ^ 0 = 0 ; 1 ^ 1 = 0; 1 ^ 0 = 1
结果为:1001(二进制) => 9 (十进制)
总结:当比较双方都为异(值不同)时,才等于1,否则为0
6.4 ~(取反)运算符
~6 = -1
过程
6 => 0110(二进制)
包括符号位在内的所有数取反
即变为1001 => -7
注意:要将二进制码转换为补码才能进行取反,取反包括符号位
图片部分来自网络引用,如有侵犯请联系作者删除