有符号右移和无符号右移,傻傻分不清楚。

接上篇文章——位运算:2的幂 。本篇文章介绍一个简单的位运算——右移。

计算机中数字都是以二进制的形式存储的,而位运算就是对数字的二进制表示进行操作。从节省硬件的角度出发(加法和减法都可以通过加法电路执行),二进制都是采用补码的形式表示,也就是每个有符号数字二进制的首位是符号位:1表示为负数,0表示为正数。相反,无符号数字的首位不表示符号。那么对数字右移的时候,高位补0还是补1呢?

在回答上面的问题之前,先插入一道题目(来自力扣191题)。
lc-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(可能会出现负数变正数,正数变负数的异常情况)。

总结
右移共分为两种:
  1. 无符号右移(将二进制位右移,低位舍弃,高位补0)
  2. 有符号右移 (将二进制位右移,低位舍弃,高位补符号位)

PS: C++ 中有无符号整型和有符号整型两种类型,可以直接显式声明变量的类型(强类型),所以只需要一种右移操作符就可以实现两种右移操作。与之相反,JavaScript中数字默认是有符号整型的,并且不能显式 指定变量的类型(弱类型),所以就要通过两种操作符来分别实现两种右移操作。

全文完
当处理位移操作时,选择无符号右移(通常表示为 `>>`)而非有符号右移(表示为 `>>>`),这取决于你所使用的编程语言和具体场景。 在C语言中,有符号右移(`>>`)和无符号右移(实际在C语言中不存在无符号右移,通常使用有符号右移和逻辑右移区分)的工作方式如下: - 有符号右移:它将最左边的位(符号位)复制到右边,保留数字的符号。对于正数,这与无符号右移相同。但对于负数,这会导致填充右边的是1而不是0。这种方式也被称为算术右移。 - 无符号右移(逻辑右移):它将右边填充0,无论原始数值的符号如何。在C语言标准中并没有直接的无符号右移运算符,但可以通过强制类型转换实现类似效果。 使用无符号右移而不是有符号右移的原因通常与数据的解释方式有关。如果你正在处理无符号整数,并且需要在右移时确保填充的是0而不是符号位的复制,那么使用有符号右移并将其结果转换为无符号类型是一种常见的做法。这样可以明确地将位移解释为逻辑右移而不是算术右移。 下面是一个C语言的例子,展示了如何使用有符号右移并将结果强制转换为无符号类型来模拟无符号右移的效果: ```c #include <stdio.h> int main() { int signedVar = -12; unsigned int shiftedVar = (unsigned int)(signedVar >> 2); printf("Shifted value: %u\n", shiftedVar); return 0; } ``` 在这个例子中,即使 `signedVar` 是负数,右移操作后将其结果强制转换为 `unsigned int`,确保了右移时右边填充的是0而不是符号位。 请注意,不同的编程语言可能有不同的位移操作符和行为。例如,在某些语言中,无符号右移可能是通过单独的运算符(比如 `>>>`)实现的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值