我需要从逻辑移位实现32位算术右移,或者,或者xor和普通整数算术运算。
我在某处读到以下内容应该有效:
(x>>N)|(((1<<N)-1)<<(32-N))
x是要移位的整数,N是要移位的位数。
这适用于负数(msb为1)数字,但不适用于正数(msb为0)。
有没有人知道总能产生正确结果的高效算法?
答案 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))
这看起来效率不高。