How to implement arithmetic right shift from logical shift?

江枫思渺然 提交于 2019-12-19 11:28:36

问题


I need to implement a 32-bit arithmetic right shift from logical shifts, and, or, xor and normal integer arithmetic operations.

I read somewhere the following is supposed to work:

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

x is the integer that will be shifted and N is the amount of bits to shift.

This works for negative (msb is 1) numbers but not for positive numbers (msb is 0).

Does anyone know an efficient algorithm that always produces the right result?


回答1:


You can use this

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

If x is negative then -(x < 0) returns -1, which have a bit pattern of all 1s, assuming 2's complement. -1 << (32 - N) will make a value which has all 1s in the top N bits and 0s in the remaining part. If x is non-negative then the latter part will always be zero, and the result will be the same as a logical shift. Alternatively it can be modified to

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

Note that it won't work for N <= 0 or N >= 32 (since shifting more than the width of type invokes UB) so you should treat those cases specifically if needed

If you're not allowed to use comparison then you can change x < 0 to (unsigned)x >> 31 and get the below equivalent ways

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



回答2:


LSR 1:

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

ASR 1:

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

An ASR consists of an LSR plus an OR.


So you want to replicate bit31 N times. The efficient solution is probably an efficient implementation of

( bit31 ? 0xFFFFFFFF : 0x00000000 ) << ( 32 - N ) )

I've come up with

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

The whole thing

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

That doesn't seem very efficient.



来源:https://stackoverflow.com/questions/25206670/how-to-implement-arithmetic-right-shift-from-logical-shift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!