逻辑右移、算术右移和循环右移的区别

58

我一直在阅读经典的《Hacker's Delight》,但是我对逻辑右移、算术右移和循环右移之间的区别感到困惑。如果我的问题显得太简单,请见谅。

还有为什么没有算术左移?


1
这与C有什么关系? - Sourav Ghosh
1
维基百科文章有什么问题吗?你对它们有什么不理解的地方? - Lundin
我不理解算术移位和逻辑移位的区别。 - Chandrahas Aroori
3个回答

127

首先要记住机器字是固定大小的。比如说4,而且你的输入是:

+---+---+---+---+
| a | b | c | d |
+---+---+---+---+

然后将所有内容向左移动一个位置,得到:

+---+---+---+---+
| b | c | d | X |
+---+---+---+---+

问题是将什么放在X的位置上?

  1. 使用shift命令将0放置在X的位置。
  2. 使用rotate命令将a放置在X的位置。

现在将所有元素向右移动一个位置,得到:

+---+---+---+---+
| X | a | b | c |
+---+---+---+---+

如何确定X的值?

  1. 使用逻辑移位,将0赋给X
  2. 使用算术移位,将a赋给X
  3. 使用循环移位,将d赋给X

大致如此。

逻辑移位对应于(左移)乘以2,(右移)除以2。

算术移位是与带符号数字的二进制补码表示相关的。在这种表示中,符号是最左边的位,然后算术移位保留符号(这称为符号扩展)。

循环移位没有普通的数学意义,甚至在计算机中也几乎已经过时了。


1
“Shift” 可以更具体地称为 “逻辑移位”,不是吗? - endolith
2
逻辑右移不会乘以2或除以2。例如,-75 >>> 1 = 90。算术右移保留符号,因此可以实现乘以2或除以2的效果。 - Jed
1
我从未说过逻辑移位是针对二进制补码数字的,只有算术移位。 - Jean-Baptiste Yunès
2
需要注意的是,算术右移向负无穷舍入,而普通有符号除法(在C中)向0截断。因此,对于有符号x编译x/2需要在SAR指令之上进行一些符号位技巧。 - Peter Cordes
1
逻辑移位和算术移位的定义是错误的。算术移位是用于除以或乘以2的,而不是逻辑移位。请纠正。 - Argus Waikhom

23

这个区别在最右边的一列中解释得很清楚了。

  • 逻辑移位将数字视为一组比特,并进行零填充。这是C语言中的>>运算符。
  • 算术移位将数字视为带符号整数(采用2的补码表示法),并“保留”最高位,如果最高位为0,则填充0,如果最高位为1,则填充1。如果被移位的数字为负数,则C语言的右移运算符具有实现定义的行为。

    例如,二进制数11100101(假设采用2的补码表示法,在十进制下为-27),使用逻辑移位向右移动3位后,变为00011100(十进制28)。这显然令人困惑。使用算术移位,符号位将被保留,结果将变为11111100(十进制-4,对于-27/8来说大约是正确的)。

  • 旋转则不做此类操作,因为最高位会被低位替换。C语言没有旋转运算符。


1
你能更清楚地解释算术移位吗?可以举个例子吗? - Chandrahas Aroori
@ChandrahasAroori,你可以在谷歌上找到大量的例子 https://en.wikipedia.org/wiki/Bitwise_operation - phuclv
"11111100(十进制约为4)" ... 这不是00000011的负数吗,应该是-3才对吧? - KMC
@KMC 这是二进制补码表示法。为了得到-4的二进制补码表示,需要取4的位表示形式,翻转所有位并加1。 - Hari

13

逻辑右移是将比特位向右移动,并将最高有效位(MSB)变为0。

例如:数字1 0 1 1 0 1 0 1的逻辑右移结果是0 1 0 1 1 0 1 0。

算术右移是将比特位向右移动,并使最高有效位(MSB)与原始数字相同。

例如:数字1 0 1 1 0 1 0 1的算术右移结果是1 1 0 1 1 0 1 0。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接