views:

1828

answers:

9

... using any comparison operators... and without using if, else, etc.

+3  A: 

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); 
}
bobwienholt
This won't work, he said no comparison operators
drewh
I think > is not allowed. Also ?: is too much like if-else.
MrDatabase
Bobs answer is a reasonable practical solution to the question without an if/else.
EvilTeach
@EvilTeach: the ?: op implies an comparison when compiled, which is not what the OP wanted.
Calyth
+4  A: 

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.

MSN

MSN
No comparison operators... ?
Lasse V. Karlsen
Well, 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
+15  A: 

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.

plinth
what about 64-bit ints or arbitrary-sized ints? :)
ADEpt
Vote down for that? Embed it in a templated or polymorphic inline function - exercise left for the astute reader.
plinth
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
ha ha! for me, that's more like magics... :)
Alex. S.
You 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
This fails if, in first step, a - b underflows...
Charles Bretana
+4  A: 

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.

Nicholas Flynt
I don't understand what the data array is for.
Kristopher Johnson
I think you meant to use the return line as an index into the data array.
Bill K
Indeed, fixed it. Thanks!
Nicholas Flynt
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
Its 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.
Nicholas Flynt
@Nicholas: make that `(sizeof(int) * CHAR_BIT - 1)`. Make sure you `#include <limits.h>`.
pmg
There are architectures where the size of a char is not 8 bits? Wow... I didn't know that. ^_^
Nicholas Flynt
+2  A: 

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

int getMax(int a, int b)
{
    for(int i=0; (i<a) || (i<b); i++) { }
    return i;
}
mspmsp
oops, no comparison ops! doh! :)
mspmsp
I also wonder if the 'for" might be construed as being like "if, else, etc."
Kristopher Johnson
O(n) - what can I say?
Trumpi
+2  A: 

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.

ADEpt
+1  A: 

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");
}
Adam Rosenfield
He said no if, meaning no coparison and cmpl is just that, a comparison.
Mecki
+2  A: 

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 shitfting 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

Dimitris
This does not seem to be correct. For example: min(-500, 0)=((-500+0)-(-500-0))/2=(-500+500)/2=0
Sander
+1  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

Bartosz Wójcik