我的方法需要使用更少的运算符

时间:2012-04-14 04:48:06

标签: c++ operators bit-manipulation

我正在完成一项家庭作业,我需要为最多24位运营商创建一个按位方法。我的代码有效...但我有25个操作员,一个太多了。有人能找到一种更有效的方法来做一段代码吗?

 int isGreater(int x, int y)
    {
      int xSign = (x>>31);
      int ySign = (y>>31);
      int check1 = (xSign & ySign) | (~xSign & ~ySign);
      int same = !((( x + ((~y) + 1) )>>31) & 0x1);
      int check2 = (check1 & same) | (~check1 & !xSign);
      int equal = ((!(x ^ y))<<31)>>31;
      return 0 | (~equal & check2);
    }

6 个答案:

答案 0 :(得分:6)

尝试更改此行:

int check1 = (xSign & ySign) | (~xSign & ~ySign);

为此:

int check1 = (xSign & ySign) | ~(xSign | ySign);

这是一个较少的运营商。

答案 1 :(得分:4)

check1仅仅是xnor。你为什么不替换它:

  int check1 = (xSign & ySign) | (~xSign & ~ySign);

用这个:

  int check1 = ~(xSign ^ ySign);

你的版本有5个按位运算符,我的版本有2个。

请注意,如果您使用此代码,您的代码会更美观:

  int check1 = !(xSign ^ ySign);

即逻辑否定而不是按位否定,但不要担心正确性,因为最后你无论如何都要取消所有高位。

答案 2 :(得分:2)

这一行:

return 0 | (~equal & check2);

可以简化为:

return (~equal & check2);

(带or的按位0没有任何效果)

答案 3 :(得分:2)

假设int是32位宽,您可以替换它:

  int equal = ((!(x ^ y))<<31)>>31;

用这个:

  int equal = ((!(x ^ y)) & 0x1;

另拯救自己。

答案 4 :(得分:1)

由于你显然可以使用添加,在我看来有一个更简单的方法:

int isGreater(int x, int y) {
    return ((unsigned)(~x + 1 + y)>>31) & 1;
}

基本思路非常简单 - 从y中减去x,并检查结果是否为负数。为了保持至少一点挑战,我假设我们不能直接进行减法,所以我们必须自己否定数字(使用二进制补码,所以翻转位并添加一个)。

五个操作员 - 如果你包括演员,则为六个。

值得注意的一点:你对same的计算本身就足够了(实际上是过度的 - 你需要消除逻辑否定)。

进行快速测试[编辑:更新测试代码以包含更多边界条件]:

int main() {
    std::cout << isGreater(1, 2) << "\n";
    std::cout << isGreater(1, 1) << "\n";
    std::cout << isGreater(2, 1) << "\n";
    std::cout << isGreater(-10, -11) << "\n";
    std::cout << isGreater(-128, 11) << "\n";
    std::cout << isGreater(INT_MIN, INT_MIN) << "\n";
    std::cout << isGreater(INT_MAX, INT_MAX) << "\n";
    return 0;
}

0
0
1
1
0
0
0
0

......一切如预期。

答案 5 :(得分:1)

我在C中提出了这个相对较短的解决方案,它可以处理从INT_MININT_MAX的所有整数。

它希望有符号整数实现为2的补码,并且它预计没有有符号溢出的副作用(已知会导致未定义的行为)。

#include <stdio.h>
#include <limits.h>

int isGreater(int x, int y)
{
  // "x > y" is equivalent to "!(x <= y)",
  // which is equivalent to "!(y >= x)",
  // which is equivalent to "!(y - x >= 0)".
  int nx = ~x + 1; // nx = -x (in 2's complement integer math)
  int r = y + nx;  // r = y - x (ultimately, we're interested in the sign of r,
                   // whether r is negative or not)

  nx ^= nx & x;    // nx contains correct sign of -x (correct for x=INT_MIN too)

  // r has the wrong sign if there's been an overflow in r = y + nx.
  // It (the r's sign) has to be inverted in that case.

  // An overflow occurs when the addends (-x and y) have the same sign
  // (both are negative or both are non-negative) and their sum's (r's) sign
  // is the opposite of the addends' sign.
  r ^= ~(nx ^ y) & (nx ^ r); // correcting the sign of r = y - x

  r >>= (CHAR_BIT * sizeof(int) - 1); // shifting by a compile-time constant

  return r & 1; // return the sign of y - x
}

int testDataSigned[] =
{
  INT_MIN,
  INT_MIN + 1,
  -1,
  0,
  1,
  INT_MAX - 1,
  INT_MAX
};

int main(void)
{
  int i, j;

  for (j = 0; j < sizeof(testDataSigned)/sizeof(testDataSigned[0]); j++)
    for (i = 0; i < sizeof(testDataSigned)/sizeof(testDataSigned[0]); i++)
      printf("%d %s %d\n",
             testDataSigned[j],
             ">\0<=" + 2*!isGreater(testDataSigned[j], testDataSigned[i]),
             testDataSigned[i]);

  return 0;
}

输出:

-2147483648 <= -2147483648
-2147483648 <= -2147483647
-2147483648 <= -1
-2147483648 <= 0
-2147483648 <= 1
-2147483648 <= 2147483646
-2147483648 <= 2147483647
-2147483647 > -2147483648
-2147483647 <= -2147483647
-2147483647 <= -1
-2147483647 <= 0
-2147483647 <= 1
-2147483647 <= 2147483646
-2147483647 <= 2147483647
-1 > -2147483648
-1 > -2147483647
-1 <= -1
-1 <= 0
-1 <= 1
-1 <= 2147483646
-1 <= 2147483647
0 > -2147483648
0 > -2147483647
0 > -1
0 <= 0
0 <= 1
0 <= 2147483646
0 <= 2147483647
1 > -2147483648
1 > -2147483647
1 > -1
1 > 0
1 <= 1
1 <= 2147483646
1 <= 2147483647
2147483646 > -2147483648
2147483646 > -2147483647
2147483646 > -1
2147483646 > 0
2147483646 > 1
2147483646 <= 2147483646
2147483646 <= 2147483647
2147483647 > -2147483648
2147483647 > -2147483647
2147483647 > -1
2147483647 > 0
2147483647 > 1
2147483647 > 2147483646
2147483647 <= 2147483647