2的补码按位减法,计算零案例

时间:2016-10-09 22:10:21

标签: c bit-manipulation bitwise-operators

[HW问题的一部分]

假设2的补码,32位字长。只允许使用signed int和常量0到0xFF。我被要求通过&#34; n&#34;来实现逻辑右移。比特(0 <= n <= 31)仅使用运算符: ! 〜&amp; ^ | +&lt;&lt; &GT;&GT;

我想我可以存储和清除符号位,执行移位,并将存储的符号位替换为新位置。

我想实施手术&#34; 31 - n&#34; (没有使用&#34; - &#34;运算符)来找到移位后存储的符号位的适当位置。

如果n是正数,我可以使用表达式:&#34; 31 +(~n + 1)&#34;但是我不相信这在n = 0的情况下会起作用。

这是我到目前为止所拥有的:

int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
   in new location */  
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x &= ~((~bit) << (31 - n)); // Replace MSbit in new location

return x;
}

感谢任何帮助和/或提示。

2 个答案:

答案 0 :(得分:0)

[编辑:已解决]

感谢大家的帮助。在这种情况下,~n + 1用于否定n,包括n = 0的情况(其中它根据需要返回0)。功能代码如下(绝不是最优雅的解决方案)。实用程序操作借鉴于:How do you set, clear, and toggle a single bit?

int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
   in new location */
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x ^= ((~bit + 1) ^ x) & (1 << (31 + (~n + 1))); // Replace MSbit in new location

return x;
}

答案 1 :(得分:0)

一个简单的解决方案是

int logicalShift(int x, int n) {
    return (x >> n) ^ (((x & 0x80000000) >> n) << 1);
}

遗憾的是,禁止使用常量0x80000000。我们可以将其计算为1 << 31(忽略C中未定义的行为),或者为节省指令,将31 - n计算为n ^ 31,然后使用以下更为人为的方法:

int logicalShift(int x, int n) {
    int b = 1 << (n ^ 31);
    return b ^ ((x >> n) + b);
}