如何以编程方式返回两个整数的最大值,而不使用任何比较运算符,也不使用 if、else 等?

发布于 2024-07-07 00:47:53 字数 78 浏览 12 评论 0原文

如何以编程方式返回两个整数的最大值,而不使用任何比较运算符,也不使用 ifelse 等?

How do I programmatically return the maximum of two integers without using any comparison operators and without using if, else, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

初心 2024-07-14 00:47:53

返回 (a > b ? a : b);

或者

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

return (a > b ? a : b);

or

int max(int a, int b)
{
        int x = (a - b) >> 31;
        int y = ~x;
        return (y & a) | (x & b); 
}
想念有你 2024-07-14 00:47:53

来自z0mbie(著名virii作家)的文章《多态游戏》,也许你会发现它很有用:

#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))

干杯

From z0mbie's (famous virii writer) article "Polymorphic Games", maybe you'll find it useful:

#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))

cheers

拥有 2024-07-14 00:47:53

我想我已经明白了。

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 位签名的。

I think I've got it.

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

Would this not work? Basically, you take the difference of the two, and then return one or the other based on the sign bit. (This is how the processor does greater than or less than anyway.) So if the sign bit is 0, return a, since a is greater than or equal to b. If the sign bit is 1, return b, because subtracting b from a caused the result to go negative, indicating that b was greater than a. Just make sure that your ints are 32bits signed.

谜兔 2024-07-14 00:47:53

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

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

And:

int a, b;

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

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

此处

max: // Will put MAX(a,b) into a

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

And:

int a, b;

min: // Will put MIN(a,b) into a

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

from here.

亚希 2024-07-14 00:47:53

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

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

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

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

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

You can have fun with arithmetically shifting (x - y) to saturate the sign bit, but this is usually enough. Or you can test the high bit, always fun.

铜锣湾横着走 2024-07-14 00:47:53

在数学世界中:

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

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

|x|代表x的绝对值。

评论:

你是对的,绝对值被忘记了。 这对于所有 a、b 正数或负数都应该有效

In the math world:

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

Apart from being mathematically correct it is not making assumptions about the bit size as shifting operations need to do.

|x| stands for the absolute value of x.

Comment:

You are right, the absolute value was forgotten. This should be valid for all a, b positive or negative

想挽留 2024-07-14 00:47:53

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

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

not as snazzy as the above... but...

int getMax(int a, int b)
{
    for(int i=0; (i<a) || (i<b); i++) { }
    return i;
}
凉城已无爱 2024-07-14 00:47:53

由于这是一个谜题,解决方案会稍微复杂一些:

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”(或“sign”?)而不是signum。

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

Since this is a puzzle, solution will be slightly convoluted:

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

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

This is Haskell, but it will be the same in any other language. C/C# folks should use "sgn" (or "sign"?) instead of signum.

Note that this will work on ints of arbitrary size and on reals as well.

陈年往事 2024-07-14 00:47:53

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


// 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");
}

This is kind of cheating, using assembly language, but it's interesting nonetheless:


// 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));
}

If you want to be strict about the rules and say that the cmpl instruction is illegal for this, then the following (less efficient) sequence will work:


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");
}
金橙橙 2024-07-14 00:47:53

这些函数使用比较,但不进行测试,并且在符合标准的系统上完全定义:

int min(int a, int b) {
    return (a <= b) * a + (b < a) * b;
}
int max(int a, int b) {
    return (a <= b) * b + (b < a) * a;
}

这是一种无需乘法的替代方法,可移植到使用二进制补码表示负数的系统:

int min(int a, int b) {
    return (a & -(a <= b)) | (b & -(b < a));
}
int max(int a, int b) {
    return (b & -(a <= b)) | (a & -(b < a));
}

两个版本都适用于所有整数类型。

请注意,gccclang 都为上述函数生成无分支代码,并且 clang 为两种替代方案生成相同的最佳代码,如上所示此 Godbolt 编译器资源管理器会话

These functions use comparisons but no tests and are fully defined on Standard compliant systems:

int min(int a, int b) {
    return (a <= b) * a + (b < a) * b;
}
int max(int a, int b) {
    return (a <= b) * b + (b < a) * a;
}

Here is an alternative without multiplications, portable to systems that use two's complement for negative numbers:

int min(int a, int b) {
    return (a & -(a <= b)) | (b & -(b < a));
}
int max(int a, int b) {
    return (b & -(a <= b)) | (a & -(b < a));
}

Both versions work for all integer types.

Note that both gcc and clang generate branchless code for the above functions, and clang generates the same optimal code for both alternatives as can be seen on this Godbolt Compiler Explorer session.

痴情换悲伤 2024-07-14 00:47:53

这是我在 C# 上的实现,仅使用 +、-、*、%、/ 运算符

using static System.Console;

int Max(int a, int b) => (a + b + Abs(a - b)) / 2;
int Abs(int x) => x * ((2 * x + 1) % 2);

WriteLine(Max(-100, -2) == -2); // true
WriteLine(Max(2, -100) == 2);   // true

This is my implementation on C# using only +, -, *, %, / operators

using static System.Console;

int Max(int a, int b) => (a + b + Abs(a - b)) / 2;
int Abs(int x) => x * ((2 * x + 1) % 2);

WriteLine(Max(-100, -2) == -2); // true
WriteLine(Max(2, -100) == 2);   // true
你与清晨阳光 2024-07-14 00:47:53
int max(int a, int b)
{
   return ((a - b) >> 31) ? b : a;
}
int max(int a, int b)
{
   return ((a - b) >> 31) ? b : a;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文