接上篇文章——位运算:2的幂 。本篇文章介绍一个简单的位运算——右移。
计算机中数字都是以二进制的形式存储的,而位运算就是对数字的二进制表示进行操作。从节省硬件的角度出发(加法和减法都可以通过加法电路执行),二进制都是采用补码的形式表示,也就是每个有符号数字二进制的首位是符号位:1表示为负数,0表示为正数。相反,无符号数字的首位不表示符号。那么对数字右移的时候,高位补0还是补1呢?
在回答上面的问题之前,先插入一道题目(来自力扣191题)。
我将用C++
和JavaScript
解题。下面是源代码:
// 作者:https://blog.csdn.net/Guza_Zh
// c++
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while(n != 0) {
if(n & 1 == 1) res++;
n >>= 1;
}
return res;
}
};
// 作者:https://blog.csdn.net/Guza_Zh
// javascript
var hammingWeight = function(n) {
let res = 0;
while(n != 0) {
if(n & 1 == 1) {
res++;
}
n >>>= 1;
}
return res;
};
思路
大致思路基本相同,将参数n
的二进制位不断右移,查看末位数字是否为1,如果为1计数器加1,直到n
变为0为止。在这道题目中,题目给的是一个无符号整数,即首位二进制数字不表示符号。所以采用无符号右移,高位补0即可。
C++
中右移用的是n >>= 1
,而 JavaScript
用的却是n >>>= 1
。它们的区别是什么呢?
这就要分别说一下这两种语言的语法啦。
C++
中只有一种右移运算符——>>
。它的定义如下:移出的低位舍弃;如果是无符号数,高位补0;如果是有符号数,高位补符号位。
而JavaScript
中有两种右移运算符——>>
和>>>
。其中>>
是有符号右移,即高位补符号位;>>>
是无符号右移,高位无脑补0(可能会出现负数变正数,正数变负数的异常情况)。
总结
右移共分为两种:- 无符号右移(将二进制位右移,低位舍弃,高位补0)
- 有符号右移 (将二进制位右移,低位舍弃,高位补符号位)