我正在使用仅按位运算符在C中创建逻辑右移位函数。这就是我所拥有的:
int logical_right_shift(int x, int n)
{
int size = sizeof(int); // size of int
// arithmetic shifts to create logical shift, return 1 for true
return (x >> n) & ~(((x >> (size << 3) - 1) << (size << 3) -1)) >> (n-1);
}
这实际上适用于所有情况,除非n = 0.我一直试图找到一种方法来解决它,所以它也适用于n = 0,但我被卡住了。
答案 0 :(得分:28)
int lsr(int x, int n)
{
return (int)((unsigned int)x >> n);
}
答案 1 :(得分:12)
这就是你需要的:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
<强>解释强>
x >> n
将n bits
改为正确。但是,如果x
为负数,则符号位(最左侧位)将复制到其右侧,例如:
假设每个int 32位,让
x = -2147483648 (10000000 00000000 00000000 00000000)
,然后是
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
等等。
因此,当n为负时,我们需要删除那些符号额外符号位。
在此假设n = 5
:
0x1 << size
将1
移至最左侧位置:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1
将1复制到其n-1
个邻居:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1!
反转所有位:
(00000111 11111111 11111111 11111111)
所以我们最终获得了一个掩码来从x >> n
中提取真正需要的东西:
(x >> n) & ~(((0x1 << size) >> n) << 1)
&
操作可以解决问题。
此功能的总费用为6
次操作。
答案 2 :(得分:3)
只需将int
存储在unsigned int
中,然后执行>>
。
(如果使用unsigned int,则不会扩展或保留符号)
答案 3 :(得分:2)
我认为问题出在你的“&gt;&gt;(n-1)”部分。如果n为0,则左侧部分将移位-1。 所以,这是我的解决方案
int logical_right_shift(int x, int n)
{
int mask = ~(-1 << n) << (32 - n);
return ~mask & ( (x >> n) | mask);
}
答案 4 :(得分:1)
派生自php's implementation of logical right shifting
function logical_right_shift( i , shift ) {
if( i & 2147483648 ) {
return ( i >> shift ) ^ ( 2147483648 >> ( shift - 1 ) );
}
return i >> shift;
}
仅限32位平台。
答案 5 :(得分:0)
与@ Ignacio的评论一样,我不知道你为什么要这样做(不像其他答案那样只对unsigned
进行演员),但是(假设有两个补码和二进制,并且签名班次是算术的:
(x >> n) + ((1 << (sizeof(int) * CHAR_BIT - n - 1)) << 1)
或:
(x >> n) ^ ((INT_MIN >> n) << 1)
答案 6 :(得分:0)
Milnex的答案很棒并且有一个很棒的解释,但遗憾的是,由于总体规模的变化,实施失败了。这是一个工作版本:
int logicalShift(int x, int n) {
int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
要将1作为最高位,并将其他所有零置于其他位置,我们需要将0x1
移至number of bits - 1
。我正在提交自己的答案,因为我对已接受答案的编辑被某种方式拒绝了。
答案 7 :(得分:0)
{{1}}
仅适用于32位