算术左、右移位与逻辑左、右移位,右移一位和除二的区别、算术溢出

当你通过搜索逻辑,算术移位运算的时候,一直寻找资料,只不过可能你没有找到满意的回答,看到这,你大概率可以结束你的搜索过程了。

这里先说一句很重要的话:

  • 正数的原码,反码,补码三者相同。
  • 负数的反码就是该负数的绝对值(正数)的原码的所有位取反,负数的补码就是反码加一。
    如果你想了解反码,原码,补码的定义还有补码为什么要+1,为什么补码比原码多表示一个数的话,你可以看我的另一篇文章《原码、反码、补码的知识总结》,

1.算术左移-逻辑左移
他们都遵循:高位丢弃,低位补零。
对于一个数字:00110011
算术左移一位的话:01100110
逻辑左移一位的话:01100110

对于他们的数值变化,左移n位,他们的数值就变为原来的2^n倍,比如左移一位,移位后的数值变为原来的2倍。
比如:十进制的52,在二进制的表达是:00110011,算术或逻辑左移一位后变为:01100110,转化为十进制就是102。102/51=2,移位后的数值变为原来的2倍。
不过,这种数值变化关系只是适用于移位后被舍弃的所有高位里面没有1,不然的话,移位的过程就会有溢出。(以上的二进制表示的都是以原码形式的。)

2.算术右移-逻辑右移
对于有符号的数,一般编译器都是对其进行算术右移,而对无符号数,都是采用逻辑右移,为什么呢?无符号的是并没有符号位,怎么移动都是补零,算术右移没有意义。
例子1:11001100、01100110

逻辑右移:
对例子都进行逻辑右移一位,得01100110、00110011。只需要将数字往右移动一位,左边补上0就可以了。

算术右移
算术右移要保持符号位不变,左边所补上的数和符号位一样。对于有符号的数:最高位就是它的符号位,0表示正,1表示负。如果是对正数的右移的话,由于正数的原码和补码一样,所以你可以直接对原码进行移位操作,但是,如果你是对负数进行移位操作的话,由于一般负数都是以补码作为储存形式的,所以对负数的移位操作要对补码进行,而不是原码。

例子2:

数值 原码 补码1(原码除符号位取反后+1)
-4 1000 0100 1111 1100
向右移一位后,补码变为 1111 1110
补码2 原码(补码减1,除符号位,其他取反) 数值
1111 1110 1000 0010 -2

可见:对例子1和2进行算术右移一位,得11100110,00110011(符号位跟着一起移动并且左边补上了符号位。)。同样的,对于右移的数值变化,相当于除以2^n,n是移位的次数。如果移位的是一个奇数的话,一个奇数除以二,会出现小数,那么这时候移位的数值取小于这个带小数的数字的最大整数。
比如: 51/2 = 25.5,取小于25.5的最大正数就是25。

3.右移一位还有除二的区别。

通过上面你可能会把除以2和右移一位等价起来,其实两者的关系有点复杂,两者只是在某一些情况下才会相等,下面我开始详细的讲解一下他们两者的关系,如果赶时间的话,可以直接看我最后的总结;

大家可以自己编写程序,看看右移一位和除以二的数字有什么区别,为了避免遗漏数据,我把数据分成了 :正偶数 正奇数 零 负偶数 负奇数 。

这是我的草稿纸,在思维导图上分析了一下,懒得敲代码了:

下面是总结:

  1. n为非负数时,>> 1和 / 2的结果是一样的
  2. n为负数且还是偶数时,>> 1和/ 2的结果是一样的
  3. n为负数且还是奇数时,>> 1和/ 2的结果是不一样的

原因是奇数除二会发生截断现象。而>> 1和/ 2在n为负奇数时截断的反向不一样。
具体的说就是:
1.除以2的算术逻辑:类似于强制转化,比如-3 / 2 = -(int)1.5 = -1,这里就是把绝对值变小了,但是加了个负号,结果就变大了。
2.对于移位,由于负数就是采用补码储存的,而补码和原码是根据模弄出来的,具体看我的《原码、反码、补码的知识总结》,补码移位后舍去小数点,相当于补码变大,原码变小,-3 >> 1 = (1101) >> 1 = (1010) = -2,所以,负数的奇数除以2会比向右移动一位大1.

4.算术溢出:
对于算术或者右移,没有溢出的情况;但是对于左移,是有溢出的情况的;
设一个八位数的二进制为X0 X1 X…X7;
对于原码,X0 = 1,那么左移的话,会有溢出的情况;
对于反码,X0 = 0 ,那么左移的话,会有溢出的情况;
也就是说对于原码,移出去的高位有1的话,那么就会有溢出,对于反码,移出去的高位有有0的话, 那么就有溢出。
对于补码,如果符号位和数据最高位相同的话,那么就不会溢出,如果符号位和数据有不同的话,那么会有溢出的情况。
其实向左移一位,可以看成是加上相同的数,所以向左移位可以转化了二进制的加法运算,接下来我用双高位判别法来讲解一下溢出;
Cs:它表征最高位(符号位)的进位情况,若符号位有进位,则Cs=1,否则,Cs=0。
Cp:它表征数值部分的最高位的进位情况,若最高数值发生进位,则Cp=1,否则Cp=0。

比如:

所以可以根据,Cs和Cp的组合判断,会不会有溢出:

由于Cs和Cp的组合与符号位和数值最高位的组合一样,有相同的结果,所以可以下结论:
当数据的最高位和符号位不同时,此时进行算术左移会导致符号的变化,从而超出该数据的设定的范围大小,从而溢出,如果相同,则不会溢出。

参考资料:
1.百度百科——算术左移位:
https://baike.baidu.com/item/算数左移位/22225819?fr=aladdin
2.CSDN博客《右移一位和除二的区别》:
https://blog.csdn.net/FlushHip/article/details/82495034
3.百度百科——补码:
https://baike.baidu.com/item/补码/6854613?fr=aladdin
4.CSDN博客《算术左移后溢出判断》:
https://blog.csdn.net/qq_35661481/article/details/78991712
5.bilibili——《无符号二进制数的算术运算和逻辑运算及运算的溢出》
https://www.bilibili.com/video/BV1vp4y1Q7Zp?from=search&seid=3267128644212277897

  • 43
    点赞
  • 124
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值