简体   繁体   English

大于C中的功能

[英]Greater than function in C

I know this is an age old question and you probably have come across this aswell, but there's a bug in my solution and I don't know how to solve it. 我知道这是一个古老的问题,你可能也遇到过这个问题,但我的解决方案中有一个错误,我不知道如何解决它。 I need to write a function that compares two integers. 我需要编写一个比较两个整数的函数。 I am only allowed to use the operations (!,~,&,^,|,+,>>,<<) and also no control structures(if,else loops etc). 我只允许使用操作(!,〜,&,^,|,+,>>,<<),也没有控制结构(if,else循环等)。

isGreater(int x, int y) {
    //returns 1 if x > y.
      return ((y+(~x+1))>>31)&1;
}

my idea is simple, we compute yx, we shift by 31 to get the sign bit, if it's negative, then we return zero else we return 1. This fails when x is negative and falsly returns 1 although it should return zero. 我的想法很简单,我们计算yx,我们移动31得到符号位,如果它是负数,那么我们返回零,否则我们返回1.当x为负时失败而falsly返回1虽然它应该返回零。 I'm stuck at this and don't know how to proceed. 我被困在这里,不知道该怎么办。

We assume that integer is 32bits and uses two's complement representation. 我们假设整数是32位并使用二进制补码表示。 This question is NOT about portability. 这个问题与可移植性无关。 Some help would be much appreciated. 一些帮助将非常感激。

Thanks in advance 提前致谢

Hacker's Delight has a chapter Comparison Predicates, which is exactly what we need here. Hacker's Delight有一章比较谓词,这正是我们在这里所需要的。

One of the things it writes is: 它写的一件事是:

x < y: (x - y) ^ ((x ^ y) & ((x - y) ^ x))

Which we can use almost directly, except that x and y should be swapped, the subtractions must be replaced by something legal, and the result appears in the top bit instead of the lowest bit. 我们几乎可以直接使用,除了交换xy之外,减法必须用合法的东西替换,结果出现在最高位而不是最低位。 Fortunately a - b == ~(~a + b) so that's not too hard. 幸运的是a - b == ~(~a + b)因此不太难。 First applying those transformations: 首先应用这些转换:

// swap x <-> y
(y - x) ^ ((y ^ x) & ((y - x) ^ y))
// rewrite subtraction
~(~y + x) ^ ((y ^ x) & (~(~y + x) ^ y))
// get answer in lsb
((~(~y + x) ^ ((y ^ x) & (~(~y + x) ^ y))) >> 31) & 1

I have a website here that says it works. 这里有一个网站说它有效。

If local variables are allowed it can be simplified a bit by factoring out the subexpression 如果允许局部变量,可以通过分解子表达式来简化一点
~(~y + x) : ~(~y + x)

int diff = ~(~y + x);
return ((diff ^ ((y ^ x) & (diff ^ y))) >> 31) & 1;

First of all let's clarify that we assume: 首先让我们澄清一下我们假设:

  • negative integers are represented in 2's complement 负整数用2的补码表示
  • int is exactly 32 bits wide and long long is exactly 64 bits wide int正好是32位宽, long long正好是64位宽
  • right shifting a negative number is an arithmetic shift 右移一个负数是算术移位

There is a problem with the (~x+1) part in your solution which is supposed to return -x . 解决方案中的(~x+1)部分存在问题,该部分应返回-x The problem is that the absolute value of INT_MIN is greater than the absolute value of INT_MAX , thus when x is INT_MIN then (~x+1) yields INT_MIN instead of -INT_MIN as you expected. 的问题是,的绝对值INT_MIN比的绝对值大INT_MAX ,从而当X是INT_MIN然后(~x+1)产生INT_MIN代替-INT_MIN如你预期。

There's also a problem with overflows in the y+(-x) part of your solution (second step). 在解决方案的y+(-x)部分也存在溢出问题(第二步)。

Now if you're allowed to use other types than int , we can solve both of these problems by casting the values to long long before the conversion, assuming that it's a 64-bit type, so that (~x+1) would return the expected result -x and y+(-x) would not cause any overflows. 现在,如果允许使用除int之外的其他类型,我们可以通过在转换之前将值转换为long long来解决这两个问题,假设它是64位类型,这样(~x+1)将返回预期的结果-xy+(-x)不会导致任何溢出。 Then, obviously, we will have to change the >>31 bit to >>63 . 那么,显然,我们必须将>>31位更改为>>63

The end solution is as follows: 最终解决方案如下:

static bool isGreater(int x, int y)  {
    long long llx = x;
    long long lly = y;
    long long result = ((lly+(~llx+1))>>63)&1;
    return result;
}

It's feasible to test it with some corner-cases, such as x == INT_MIN , x == 0 and x == INT_MAX : 用一些角点测试它是可行的,例如x == INT_MINx == 0x == INT_MAX

int main(void) {
    int x = INT_MIN;
    for (long long y = INT_MIN; y <= INT_MAX; ++y) {
        assert(isGreater(x, y) == (x > y));
    }
    x = INT_MAX;
    for (long long y = INT_MIN; y <= INT_MAX; ++y) {
        assert(isGreater(x, y) == (x > y));
    }
    x = 0;
    for (long long y = INT_MIN; y <= INT_MAX; ++y) {
        assert(isGreater(x, y) == (x > y));
    }
}

This was successful on my particular machine with my particular compiler. 这在我的特定机器上使用我的特定编译器是成功的。 The testing took 163 seconds. 测试耗时163秒。

But again, this depends on being able to use other types than int (but then again with more work you could emulate long long with int ). 但同样,这取决于能否使用除int之外的其他类型(但是再次使用更多的工作,您可以使用int模拟long long )。

This whole thing could be more portable if you used int32_t and int64_t instead of int and long long , accordingly. 如果您使用int32_tint64_t而不是intlong long ,那么整个事情可以更加可移植。 However, it still would not be portable: 但是,它仍然不可移植:

ISO/IEC 9899:2011 §6.5.7 Bitwise shift operators ISO / IEC 9899:2011§6.5.7按位移位算子

5 The result of E1 >> E2is E1 right-shifted E2 bit positions. 5 E1 >> E2的结果右移E2位位置。 If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. 如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。 If E1 has a signed type and a negative value, the resulting value is implementation-defined. 如果E1具有带符号类型和负值,则结果值是实现定义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C 函数从按递增顺序排序的数组中返回大于给定数字的最小数字的索引 - C function that returns index of smallest number greater than a given number from an array sorted in increased order 使用读取功能使用C(大于4GB)读取大文件,导致问题 - Reading a large file using C (greater than 4GB) using read function, causing problems C最佳函数,以获取小于,等于和大于某个值的元素上的拆分数组 - C best function to get split array on elements less, equals and greater than some value 为什么这比功能大? - Why does this greater than function work? C程序冻结的单词长度大于6 - C program freezes for word lengths greater than 6 使用fread功能:要读取的大小大于可读取的大小 - Using fread function: size to be read is greater than available for reading C比较两个指针大于一个是否为null - C compare two pointers greater than if one is null C宏获得大于给定数的2的最小幂 - C macro to get the smallest power of two greater than a given number 将大于long类型最大值的值传递给C中的fseek - Pass a value greater than maximum value of long type to fseek in C 在C语言中将原始24位像素图缩放到大于50%的算法 - Algorithm to scale a raw 24 bit pixelmap to greater than 50% in C
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM