如何在不使用任何比较运算符且不使用if,else等的情况下以编程方式返回两个整数的最大值?

StackOverflow https://stackoverflow.com/questions/227383

如何在不使用任何比较运算符的情况下以编程方式返回最多两个整数,而不使用 if else 等?

有帮助吗?

解决方案

max://将MAX(a,b)放入

a -= b;
a &= (~a) >> 31;
a += b;

int a,b;

min://将MIN(a,b)放入

a -= b;
a &= a >> 31;
a += b;

来自此处

其他提示

http://www.graphics.stanford.edu/~seander /bithacks.html#IntegerMinOrMax

r = x - ((x - y) & -(x < y)); // max(x, y)

你可以通过算术移位(x - y)来使符号位饱和,但这通常就足够了。或者你可以测试高位,总是很有趣。

我想我已经得到了它。

int data[2] = {a,b};
int c = a - b;
return data[(int)((c & 0x80000000) >> 31)];

这不起作用吗?基本上,你取两者的差异,然后根据符号位返回一个或另一个。 (这就是处理器无论如何都要大于或小于的程度。)因此,如果符号位为0,则返回a,因为a大于或等于b。如果符号位为1,则返回b,因为从a中减去b导致结果变为负数,表明b大于a。只需确保您的整数是32位签名。

在数学世界中:

max(a+b) = ( (a+b) + |(a-b)| ) / 2
min(a-b) = ( (a+b) - |(a-b)| ) / 2

除了在数学上正确之外,它不会像移位操作那样对位大小做出假设。

| x | 代表x的绝对值。

的评论:

你是对的,绝对的价值被遗忘了。这应该适用于所有a,b正面或负面

返回(a&gt; b?a:b);

int max(int a, int b)
{
        int x = (a - b) >> 31;
        int y = ~x;
        return (y & a) | (x & b); 
}

不像上面那样时髦......但是......

int getMax(int a, int b)
{
    for(int i=0; (i<a) || (i<b); i++) { }
    return i;
}

由于这是一个谜题,解决方案会有点复杂:

let greater x y = signum (1+signum (x-y))

let max a b = (greater a b)*a + (greater b a)*b

这是Haskell,但在任何其他语言中都是一样的。 C / C#人应该使用“sgn” (或“签署”?)而不是签名。

请注意,这将适用于任意大小和实数的内联。

来自z0mbie(着名的virii作家)文章“Polymorphic Games”,也许你会发现它很有用:

#define H0(x)       (((signed)(x)) >> (sizeof((signed)(x))*8-1))
#define H1(a,b)     H0((a)-(b))

#define MIN1(a,b)   ((a)+(H1(b,a) & ((b)-(a))))
#define MIN2(a,b)   ((a)-(H1(b,a) & ((a)-(b))))
#define MIN3(a,b)   ((b)-(H1(a,b) & ((b)-(a))))
#define MIN4(a,b)   ((b)+(H1(a,b) & ((a)-(b))))
//#define MIN5(a,b)   ((a)<(b)?(a):(b))
//#define MIN6(a,b)   ((a)>(b)?(b):(a))
//#define MIN7(a,b)   ((b)>(a)?(a):(b))
//#define MIN8(a,b)   ((b)<(a)?(b):(a))

#define MAX1(a,b)   ((a)+(H1(a,b) & ((b)-(a))))
#define MAX2(a,b)   ((a)-(H1(a,b) & ((a)-(b))))
#define MAX3(a,b)   ((b)-(H1(b,a) & ((b)-(a))))
#define MAX4(a,b)   ((b)+(H1(b,a) & ((a)-(b))))
//#define MAX5(a,b)   ((a)<(b)?(b):(a))
//#define MAX6(a,b)   ((a)>(b)?(a):(b))
//#define MAX7(a,b)   ((b)>(a)?(b):(a))
//#define MAX8(a,b)   ((b)<(a)?(a):(b))

#define ABS1(a)     (((a)^H0(a))-H0(a))
//#define ABS2(a)     ((a)>0?(a):-(a))
//#define ABS3(a)     ((a)>=0?(a):-(a))
//#define ABS4(a)     ((a)<0?-(a):(a))
//#define ABS5(a)     ((a)<=0?-(a):(a))

欢呼声

这是一种使用汇编语言的作弊,但它仍然很有趣:


// GCC inline assembly
int max(int a, int b)
{
  __asm__("movl %0, %%eax\n\t"   // %eax = a
          "cmpl %%eax, %1\n\t"   // compare a to b
          "cmovg %1, %%eax"      // %eax = b if b>a
         :: "r"(a), "r"(b));
}

如果你想严格遵守规则并且说 cmpl 指令对此是非法的,那么以下(效率较低)序列将起作用:


int max(int a, int b)
{
  __asm__("movl %0, %%eax\n\t"
      "subl %1, %%eax\n\t"
          "cmovge %0, %%eax\n\t"
          "cmovl %1, %%eax"
         :: "r"(a), "r"(b)
         :"%eax");
}
int max(int a, int b)
{
   return ((a - b) >> 31) ? b : a;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top