关于算术移位,逻辑移位的一些思考

今天研究编码方式时,遇见了大小端问题,准备用IDEA测一下本地系统是大端还是小端模式时,又遇到了移位操作,重新温习了一下,特此记录。

注:以下讨论的内容,皆以补码作为数据表示形式,实际计算机系统中也以补码来存储数据。(为什么要强调以补码为前提呢?戳这里

首先从理论的角度来说,
关于算术移位逻辑移位
通俗的理解如下:

  • 逻辑移位:仅做最纯粹的移位操作,不考虑其他情况
  • 算术移位:移位时需要做算术方面的考虑,即考虑到符号位

逻辑移位时,补位都是补0,;算术移位时,对于需要补位的高位(右移),补符号位,需要补位的低位(左移),仍然补0。所以,只有算术右移,是比较特殊的,需要补符号位,其余的移位操作,都是补0

算术移位逻辑移位比较

  • 逻辑左移:高位丢弃,低位补0,在不发生溢出的情况下,效果相当于乘2
  • 算术左移:等同于逻辑左移
  • 逻辑右移:低位丢弃,高位补0
  • 算术右移:低位丢弃,高位补符号位,效果相当于除以2,但可能发生精度丢失

在Java中,移位运算符共有3个:<<>>>>>
可将前2个视为算术移位运算符,第3个为逻辑右移

  • << 左移,a << 1可实现乘2的效果(前提是不发生溢出)
  • >> 右移,a >> 2 可实现除以2的效果(可能发生精度丢失)
  • >>> 逻辑右移,高位补0,一般不使用

关于<<运算符的溢出判断标准:

先上结论:若数x的二进制表示的前n+1位全部相同(全为1或全为0),则此时对x左移最多n位,是不会发生溢出的;否则,将发生溢出。

这里可以自己去分2种情况做检验,前n位全为1和全为0,随便举几个数字,做一下左移操作,在将补码转换为原码,再计算出对应的十进制数字,与原数字做比较即可,不赘述。

附:

关于为什么强调以补码为前提

其实在文首讨论对算术移位的通俗理解时,我说算术移位就是要将符号位考虑进来,那么如果数据是用原码来表示(其实原码也是最直观,最符合人的思维的数据表示形式),那么严格来讲,我认为在做算术移位时,符号位应该是不动的,所以算术左移等同于逻辑左移,其实严格来说并不是,只是在补码形式下,两者在实际运用中效果是等同的。比如,二进制数10110(原码表示),其十进制为-6,那么对其做算术移位,若算术左移1位,那么符号位不动,仅对后面的4位做移位,得11100,转换为十进制为-12;那么如果算术右移1位,符号位不动,得10011,转换为十进制为-3(以原码形式存储数据的话,算术移位其实补位都应当补0,符号位不动即可)。然而在JAVA中,移位操作是不会让符号位固定的(符号位也参与移位),而我们知道,为了方便负数的运算,计算机里的数都是以补码来存储的,-6用补码表示则为11010,此时你再去尝试做一下算术左移和右移,就明白为什么本文前面说算术左移的溢出判断标准是那样,以及算术右移为什么不是补0而是补符号位了。

以上

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值