如何实现逻辑移位的算术右移?

时间:2014-08-08 15:13:14

标签: bit-manipulation bit-shift signed

我需要从逻辑移位实现32位算术右移,或者,或者xor和普通整数算术运算。

我在某处读到以下内容应该有效:

(x>>N)|(((1<<N)-1)<<(32-N))

x是要移位的整数,N是要移位的位数。

这适用于负数(msb为1)数字,但不适用于正数(msb为0)。

有没有人知道总能产生正确结果的高效算法?

2 个答案:

答案 0 :(得分:1)

您可以使用此

(x >> N) | (-(x < 0) << (32 - N))

如果x为负,则-(x < 0)返回-1,其具有全1 的位模式,假设为2的补码。 -1 << (32 - N)将生成一个值,该值在前N位中为全1,在剩余部分中为0。如果x是非负的,则后一部分将始终为零,结果将与逻辑移位相同。或者,它可以修改为

(x >> N) | ~(((x < 0) << (32 - N)) - 1)

请注意,它不适用于N <= 0或N&gt; = 32(因为shifting more than the width of type invokes UB)所以您应该在需要时专门处理这些案例

如果您不允许使用比较,那么您可以将x < 0更改为(unsigned)x >> 31并获得以下等效方式

(x >> N) | (-((unsigned)x >> 31) << (32 - N))
(x >> N) | ((~0*(unsigned)x >> 31) << (32 - N))
(x >> N) | ~((((unsigned)x >> 31) << (32 - N)) - 1)

答案 1 :(得分:0)

LSR 1:

+---+---+---+---
|   |   |   | ...
+---+---+---+---
   \   \   \   \
    \   \   \  
     \   \   \
+---+---+---+---
| 0 |   |   | ...
+---+---+---+---

ASR 1:

+---+---+---+---
|   |   |   | ...
+---+---+---+---
  |\   \   \   \
  | \   \   \  
  |  \   \   \
+---+---+---+---
|   |   |   | ...
+---+---+---+---

ASR由LSR和OR组成。


所以你想复制bit31 N次。

可能是一种有效的解决方案
( bit31 ? 0xFFFFFFFF : 0x00000000 ) << ( 32 - N ) )

我想出了

LSL(SUB(LSR(NOT(X), 31), 1), SUB(32, N))

整件事

OR(LSL(SUB(LSR(NOT(X), 31), 1), SUB(32, N)), LSR(X, N))

这看起来效率不高。