为啥逻辑左移与算术左移相同?
Posted
技术标签:
【中文标题】为啥逻辑左移与算术左移相同?【英文标题】:Why is Logical Shift Left the Same as Arithmetic Shift Left?为什么逻辑左移与算术左移相同? 【发布时间】:2021-09-23 19:39:20 【问题描述】:我知道那里有类似的问题。但我很好奇的是为什么逻辑左移和算术左移是一样的。
我知道算术左移和逻辑左移在技术上是相同的,因为 msb(最高有效位)在这两种操作中都没有保留,并且 msb 被替换为 0,并且所有位都只是“移位” “ 剩下。但是,为什么我们不能保留 msb 同时将剩余的位左移以进行左算术移位?算术右移保留了 msb 来表示有符号位,那么我们为什么不对算术左移做同样的事情呢?
例如,在Java中:“>>”是逻辑右移,“>>”是算术右移,但“
【问题讨论】:
左移 1 将最高有效位替换为之前的第二个最高有效位 - 它用 0 替换 最低 有效位。当然,会有没有什么能阻止您定义自己的操作,该操作执行左移保留最低有效位,但这并不是一个足够有用的操作,因为它不能成为任何流行语言的原语。 另见:en.wikipedia.org/wiki/… 所以,如果我理解正确,在算术右移中,最高有效位被保留,因为 1 的 msb 将被解释为负号,而 0 将被解释为一个积极的迹象。如果是这种情况,为什么我们不能对算术左移做同样的事情? 当我们执行算术左移时,我们不希望负数也保持负数吗?因为左移相当于除以 2?如果我们只是简单地向左移动,在某些情况下,将 1 的最高位和 0 的第二位移除,我们不是在改变数字的符号吗? 如果你左移一个负数变成一个正数,那么你得到的结果就像你乘以 2 一样;无论哪种方式,它都是整数溢出并且您没有得到“正确”的答案,因为整数的固定宽度不足以代表“正确”的答案。如果您改为保留符号位,那么乘以 2 仍然不会得到“正确”答案,出于同样的原因 - 您只会得到错误的否定结果,而不是错误的肯定结果。 【参考方案1】:正常的左右算术移位都保留符号位。所以
-32 >> 1 == -16
-16 << 1 == -32
因此,从某种意义上说,算术左移既是算术也是逻辑的,因为算术和非算术位操作都可以完成。
但是需要特别处理一个右逻辑移位来移位符号位并用0位填充左侧。
-1 >>> 1 == 2147483647
如果要完成非算术位操作,这是必不可少的。但是如何进行保留符号的左算术移位?
考虑一个 4 位寄存器,msb
是符号并且它被保留。想象一下<<
运算符的工作方式如下
0111 == 7
0111 << 1 == 0110 == 6
0110 << 1 == 0100 == 4
0100 << 1 == 0000 == 0
Imo,那用处不大。
【讨论】:
【参考方案2】:但是,为什么我们不能保留 msb,同时将其余位左移以进行左算术移位?
我们可以做到,例如这里是该想法的 java 实现:
int shiftLeftPreserveMSB(int x, int k)
return (x & Integer.MIN_VALUE) | ((x << k) & Integer.MAX_VALUE);
但这真的有用吗?例如,它有一个可疑的属性,即每当结果与x << k
不同时,都不结果匹配(long)x << k
。从算术的角度来看,这似乎不是很有用。也许是这样,但至少这是一个奇怪的操作。这样的操作可能还有其他用途,例如在 bithacks 中,尽管我不知道有任何此类用途。
【讨论】:
以上是关于为啥逻辑左移与算术左移相同?的主要内容,如果未能解决你的问题,请参考以下文章