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

- 20,225
- 7
- 37
- 83

- 43,245
- 41
- 111
- 153
-
5-1: Why no comparisons? Seems like an artificial question to me. – Alex Lyman Oct 22 '08 at 20:28
-
Is there a point to this beyond your curiosity? – Erik Forbes Oct 22 '08 at 20:29
-
It's just an interview question :-] – MrDatabase Oct 22 '08 at 20:31
-
No there's no point other than curiosity, sorry. – MrDatabase Oct 22 '08 at 20:32
-
This solution doesn't appear to me to work if a or b is negative. If they're equal then clz returns 32 and the second line does an invalid shift by -1 – Steve Jessop Oct 22 '08 at 20:35
-
17Why do these bizarre puzzles show up as interview questions? Do mechanics get asked things like how they would get a gasoline engine to run without spark plugs? – Michael Burr Oct 22 '08 at 20:41
-
One could charitably say that a question like this demonstrates that someone understands boolean algebra. But I agree that puzzle questions like these don't really help gauge a candidate's ability. – Kristopher Johnson Oct 22 '08 at 20:43
-
1Maybe the idea is that the candidate scores maximum points by asking why on earth anyone would care to know the answer :-) It would make sense for an assembly programming or compiler writing job, but it's something you never need to do in C. The compiler writer will have optimised (a – Steve Jessop Oct 22 '08 at 21:04
-
It's something you'd never need to do in most Assembly languages, as well. Really a pointless question for an interview. – Mark Bessey Oct 22 '08 at 21:08
-
No worries MrDatabase - I was merely curious to see if there was a specific use case you had in mind for this. – Erik Forbes Oct 23 '08 at 02:06
-
I would argue that the value of any thought-provoking interview question isn't to get the right answer, but rather the willingness to give the question the thought that it's due. That said, I would also hope that the presence of such a question doesn't mean such tricksy programming would be valued. – Erik Forbes Oct 23 '08 at 02:14
-
1@Mark: the reason I say appropriate for assembler programmers is just that tricks to avoid jumps are pretty standard fare (unless your CPU optimises microcode really well). On ARM for instance clearly you would use conditionals, so the question would be "how to do this without a branch". Maybe. – Steve Jessop Oct 23 '08 at 03:31
-
4@Michael Burr: at least one mechanic got asked how to get a gasoline engine to run without spark plugs. His name was "Diesel". – MusiGenesis Mar 29 '10 at 12:01
-
@MusiGenesis: But then it's not a gasoline enginer anymore, is it? :) Also, do you mean to say that these puzzle questions are looking to find people who can invent entirely new paradigms for engineering? Inventing new languages? Changing how the entire industry works? For some reason, I don't think this is the kind of question Stroustrup, Torvalds or Stallman would be asked at a job interview. – Michael Burr Mar 29 '10 at 14:28
-
@Michael Burr: if those three are actually interviewing, maybe they're not so hot after all? :) Also, a diesel engine can run on nearly anything, including gasoline. – MusiGenesis Mar 29 '10 at 14:50
12 Answers
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.

- 1,972
- 16
- 25

- 48,267
- 11
- 78
- 120
-
1
-
1Vote down for that? Embed it in a templated or polymorphic inline function - exercise left for the astute reader. – plinth Oct 22 '08 at 20:54
-
By definition polymorphic functions can't be inline. You need to evaluate the function call by vtable at runtime. But neat solution, doesn't work for unsigned ints though... – Greg Rogers Oct 22 '08 at 21:27
-
1You should mention this depends on signed right shifts preserving sign. This is not guaranteed by the C standard afaik. However it does work under gcc for me. – freespace Oct 23 '08 at 02:22
-
@VinayakGarg - if a == b then the value of a is zero until the last step, at which point it is added to b. It works. – hoodaticus Dec 15 '16 at 19:49
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.
-
4Well, to be perfectly pedantic, you should be talking about branches, not comparison operators, since branches are far more likely to cause performance issues. But anyways, that's why I added the additional commentary below, since x < y is equivalent to getting the high bit of x - y. – MSN Oct 22 '08 at 20:54
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
-
This does not seem to be correct. For example: min(-500, 0)=((-500+0)-(-500-0))/2=(-500+500)/2=0 – Sander May 15 '09 at 08:54
-
2Aren't you just hiding the comparison here? Since `abs(x) := x >= 0 ? x : -x`. So you will need a branching operator just the same. Of course you can prevent branching by using an &-mask, but then you'd have to make assumptions on the bit count of the operands.. – marcusklaas Dec 12 '14 at 01:02
-
1"should be valid for all a,b positive or negative" does not apply to `int` as `a+b` can readily overflow. – chux - Reinstate Monica Aug 30 '15 at 20:18
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.

- 7,088
- 12
- 49
- 69
-
-
I think you meant to use the return line as an index into the data array. – Bill K Oct 22 '08 at 20:46
-
In case if you want the above code to work in Java, You may need to substitute ">>" with ">>>" .Using ">>" operator will result in negative index where a and b have negative values especially if a < b. For example, try a=-4 and b =-3 – BlueGene Oct 27 '08 at 23:24
-
1Its C code. Anyway, if you wanted it to be really "complete" in C, you need to substitute 31 with "(sizeof(int) * 8 - 1)", which will work regardless of the architecture. Usually though, I work on a 32bit architecture, so I'm used to assuming a size of 32 bits. – Blank Oct 29 '08 at 18:59
-
@Nicholas: make that `(sizeof(int) * CHAR_BIT - 1)`. Make sure you `#include
`. – pmg Nov 07 '09 at 16:02 -
There are architectures where the size of a char is not 8 bits? Wow... I didn't know that. ^_^ – Blank Nov 12 '09 at 18:21
-
@pmg Make that `width` where width is the size of the type without the padding bits. :-) – 2501 Apr 21 '16 at 12:03
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

- 1,079
- 2
- 13
- 31
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);
}

- 17,420
- 3
- 40
- 48
-
-
Bobs answer is a reasonable practical solution to the question without an if/else. – EvilTeach Oct 22 '08 at 20:28
-
@EvilTeach: the ?: op implies an comparison when compiled, which is not what the OP wanted. – Calyth Jan 12 '09 at 21:48
not as snazzy as the above... but...
int getMax(int a, int b)
{
for(int i=0; (i<a) || (i<b); i++) { }
return i;
}

- 953
- 6
- 7
-
-
I also wonder if the 'for" might be construed as being like "if, else, etc." – Kristopher Johnson Oct 22 '08 at 20:37
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.

- 5,504
- 1
- 25
- 32
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");
}

- 390,455
- 97
- 512
- 589
-
2He said no if, meaning no coparison and cmpl is just that, a comparison. – Mecki Oct 22 '08 at 21:08
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.

- 131,814
- 10
- 121
- 189
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

- 2,013
- 3
- 18
- 37
-
`(2 * x + 1)` overflows for about half of the range of type `int`. `a - b` exceeds the range of `int` quite easily too. – chqrlie Feb 02 '21 at 22:11
-
@chqrlie Yes, you right. This code not for production use, it's for educational purpose – giokoguashvili Feb 03 '21 at 12:49