仅使用“〜& ^ | +<<>> =”运算符和20个运算来实现逻辑右移

时间:2013-10-05 21:56:05

标签: c bitwise-operators

所以我有一个赋值,我必须在c中编写一个函数,它只使用〜,&的按位运算。 ,^,| ,+,<< ,>> ,和=。我只需要使用20次操作。并且我不允许使用控制结构,例如if-else,for,while,switch,或其他任何可以在条件块中使用代码的东西。 类型转换也是,并且未在函数头中声明的字节(给我),限制为1个字节或8位值;所以我有十六进制到FF。

我必须编写的函数是逻辑右移。因此,不是填充符号位的位,而是填充0的

这就是我所做的:

int logicalShift(int x, int n) {
    int op=0xFFFFFFFF;
    int tcn=(~n+1);
    int sizeshift=0x20 & tcn;
    op=(op<<sizeshift);
    return ((x>>n) + (op));
}

这是我期望得到的(对于x = 0x80000000,n = 0x01) 我希望得到0x40000000,即十进制的1073741824。这就是我得到的。 但是(对于x = 0x80000000,并且n = 0x0 我希望得到0x80000000,但是我得到0x7fffffff这是我的答案减去一点。我可以添加一点,但它弄乱了第一个答案。所以我做错了,我有一个案子而不是另一个案子。我也试过了。

int logicalShift(int x, int n) {
    int op=0xFFFFFFFF;
    int tcn=(~n+1);
    int sizeshift=0x20 & tcn;
    op=(op<<sizeshift);
    return ((x>>n) + (op  ^ ~n));
}

我认为,如果我对0的情况下的所有1的符号位进行异或运算,那么当它通过编译器转换为2的补码时,我会得到一些非负的(也就是)0x7fffffff。它最终使情况变得更糟。请让我指出正确的方向我应该考虑什么以及为什么?

2 个答案:

答案 0 :(得分:4)

逻辑移位和算术移位之间的差异是从左侧移入的位。要在算术方面实现逻辑移位,您可以执行算术移位,然后清除新位。在伪代码中:

  1. 生成掩码,当与结果进行AND运算时,将清除最左侧的 n 位。
  2. 右移 n 位。
  3. 和面具。
  4. 使用AND意味着您不必关心哪些位被移入。您只是想无条件地将它们设置为0.。

    然后问题是如何生成掩码。我会把它作为锻炼给你。

答案 1 :(得分:0)

如果未设置符号位,(x >> n) == (x >>> n)。如果设置了符号位,我们会在执行移位之前将其屏蔽掉,然后将其添加回来:(x & 0x7FFFFFFF) >> n | (0x40000000 >> (n - 1))

如果我们知道,我们拥有的两种情况中的哪一种,计算变得更容易。如果我们可以使用if,我们可以将这两种情况结合起来。我们必须模仿条件。

int signBit1 = (x & 0x7FFFFFFF) >> n | (0x40000000 >> (n - 1));
int signBit0 = x >> n;
var signBitIsolated = x & 0x80000000; // either 0 or 0x80000000
var signMask = signBitIsolated >> 31; //either 0 or 0xFFFFFFFF
var combined = (signBit0 & ~signMask) | (signBit1 & signMask);
return combined;

我们通过生成全零或全1掩码以及两种情况来模拟条件。

我认为您说输入域限制为一个字节。同样的想法适用,但有不同的常量。