Take a look at the "bit-twiddling hacks" page and study how maximum/minimum are implemented.
If you can figure out how the maximum for two numbers works, then you can generalize the case for three numbers.
Let me explain to you the two-numbers case for getting the maximum value:
-(a<b)
can either return -1 or 0, then you can have either 11111111 11111111 11111111 11111111
(-1 in two's complement for an int) or 00000000 00000000 00000000 00000000
(-0 == 0 for an int).
Remembering that a^b^b = a
and that a^b^a = b
(doesn't matter what the order is, this is the xor operation), you have that in the first case:
- If
a < b
you need to return b as result, so
a ^ ((a ^ b) & -(a < b))
must be equal to a ^ a ^ b
.. and in fact it is since -(a<b)
returns 11111111 11111111 11111111 11111111
, and an and-bitwise & operated on 11111111 11111111 11111111 11111111
for an unsigned integer leaves the number unchanged... thus a ^ a ^ b = b
. This is the maximum.
- If
a > b
then a < b
is false, thus (anything & 00000000 00000000 00000000 00000000)
is 0. And thus you have a ^ 0
, which is, a. The maximum.
And finally we have the solution generalized for three numbers:
#include <stdio.h>
int getMax(unsigned int a, unsigned int b, unsigned int c) {
int temp = a ^ ((a ^ b) & -(a < b)) ;
int r = c ^ ((c ^ temp) & -(c < temp));
return r;
}
int main(void) {
unsigned int a = 3, b = 1, c = 9;
printf("%d", getMax(a,b,c));
return 0;
}
Edit: if you're not allowed to use "<" then use the second version
x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1)));
and keep in mind the following excerpt
Note that the 1989 ANSI C specification doesn't specify the result of
signed right-shift, so these aren't portable. If exceptions are thrown
on overflows, then the values of x and y should be unsigned or cast to
unsigned for the subtractions to avoid unnecessarily throwing an
exception, however the right-shift needs a signed operand to produce
all one bits when negative, so cast to signed there
Edit II: this should work with the specification you posted:
#include <stdio.h>
int getMax(int x, int y, int z) {
int r = (x + ~((x+~y+1) & ((x+~y+1) >> 31))+1); // if possible use sizeof(int)*sizeof(char)+~0 instead of 31
int r2 = (z + ~((z+~r+1) & ((z+~r+1) >> 31))+1); // if possible use sizeof(int)*sizeof(char)+~0 instead of 31
return r2;
}
int main(void) {
unsigned int a = 5, b = 7, c = 1;
printf("%d", getMax(a,b,c));
return 0;
}
Notice that it would be better if you could use sizeof() instead of just assuming that an int is 4 bytes (it isn't true on all platforms).