为什么右移有「有无」符号之别,而左移却没有?

📝 摘要:在众多语言中,都提供了关于位操作符,但 为什么右移有“有无”符号之别,而左移却没有?,本文一步步讲述左移、有符号右移、无符号右移,以此来揭开位移的面纱,最终探究答案,囿于本人知识与能力,如有纰漏,敬请指出!

1. 引言

在 JavaScript 和 Java 语言中,针对二进制进行移位的位操作符有:左移 <<、有符号右移 >>、无符号右移 >>>,首先我们先从概念上去剖析它们,这里引用《计算机组成原理教程》书中的一段描述:

计算机中机器数的字长往往是固定的,当机器数左移 n 位或右移 n 位时,必然会使其 n 位低位或 n 位高位出现空位。那么,对空出的空位应该添补 0 还是 1 呢?这与机器数采用有符号数还是无符号数有关。对无符号数的移位称为逻辑移位,对有符号数的移位称为算术移位。

考虑符号位的位操作都称为算数移位,“算数”,就是用于计算所用;不考虑符号位的都成为逻辑移位,“逻辑”,就是简单的移位,一般用于压缩编码等单纯移位,不需要考虑符号位。以这两个概念作为分类可将移位的位操作符分为:

分类左移右移
算数移位左移<<有符号右移符号>>
逻辑移位无符号右移符号>>>

看完这个分类表,对强迫症来说似乎不那么友好,这也就引出来本博客的题目:为什么右移有“有无”符号之别,而左移却没有?

回答这个问题之前,还是得了解移位操作,为了简化描述,我们以 5 位二进制数(最高位为符号位)来作为举例:

2. 左移

对于数值 3,它的二进制位 00011,左移前可以表示如下:

下标4(符号位)3210
位数00011

左移两位 3 << 2注意符号位不参与移位

下标4(符号位)3210
位数00011

高位舍弃,低位补 0,结果可得 12

下标4(符号位)3210
位数01100

对于 -3,左移前可以表示如下:

下标43210
位数11101

在计算机底层中,负数以补码的形式存储,正数的补码和原码一样,负数的补码由除符号位的原码(该数的绝对值)的反码再加一可得

左移两位 -3 << 2注意符号位不参与移位

下标4(符号位)3210
位数11101

高位舍弃,低位补 0,结果可得 -12(注意结果仍为补码)

下标43210
位数10100

这里结果的计算涉及到原码和补码的转换,可以参考博客:补码和原码的转化过程

3. 有符号右移

为了更好的举例,这里我们使用数值 5,它的二进制位 00101,有符号右移前可以表示如下:

下标4(符号位)3210
位数00101

有符号右移两位5 >> 2注意符号位不参与移位

下标43210
位数00101

高位补符号位,低位舍弃,有符号右移结果为 1

下标4(符号位)3210
位数00001

❗️注意,高位是补符号位,正数补 0,看不出效果,当对于负数来说,却又天壤之别。


对于 -5,有符号右移前可以表示如下:

下标43210
位数11011

有符号右移两位 -5 >> 2注意符号位不参与移位

下标4(符号位)3210
位数11011

高位补符号位,低位舍弃,结果为 -2

下标4(符号位)3210
位数11110

4. 无符号右移

无符号右移把整个数当作无符号数来看待,再进行移动

对于 5,无符号右移前可以表示如下:

下标43210
位数00101

无符号右移两位 5 >>> 2

下标43210
位数00101

高位补 0,低位舍弃,无符号右移结果为 1

下标43210
位数00001

对于 -5,无符号右移前可以表示如下:

下标43210
位数11011

无符号右移两位 -5 >>> 2,注意,此时将整个数当作无符号数来看待

下标43210
位数11011

高位补 0,低位舍弃,此时结果变为正数 6

下标43210
位数00110

5. 总结

分类操作结果
左移3 << 212
-3 << 2-12
有符号右移5 >> 21
-5 >> 2-2
无符号右移5 >>> 21
-5 >>> 26
  1. 我们可以看到,对于正数,有符号右移和无符号右移都是一样的,但是对于负数,且大相径庭,原值 -5,无符号右移后变成了 6
  2. 我们再以补位的视角去对比完左移和右移,就会发现,右移后高位是空出来的,对于空出来的高位,就需要去考虑补 0 还是补 1,而左移后高位时被舍弃掉的,根本不需要“补位”一说。这也就解释了为什么右移有“有无”符号之别,而左移却没有,因为根本就没有必要。

6. 参考资料

[1] 千万别小看这些运算符背后的逻辑:
https://developer.aliyun.com/article/763951
[2] 补码和原码的转化过程:https://www.cnblogs.com/wxf0701/archive/2008/08/14/1267639.html

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值