I don't believe it's possible to solve if you want the code to work without assuming a certain size of int
and representation. But this works for 32-bit ints and two's complement representation:
int is_zero(int x) {
int zero = (x^x);
int one = ~(~zero + ~zero);
int five = one + one + one + one + one;
int thirtyone = (one << five) + ~zero;
return ~((x >> thirtyone) | ((~x + one) >> thirtyone));
}
It uses multiple assignments to construct the constants, but the code could be folded into a single expression if necessary.
How it works
(x >> thirtyone)
is -1 if x
is negative and 0 otherwise.
Similarly, (~x + one) >> thirtyone
is -1 if x
is positive, and 0 otherwise.
The bitwise or
of these two expressions is 0
if x
is zero, and -1
otherwise. A bitwise ~
then gives -1 if x
is zero, and 0 otherwise.
(Almost) word-size independent solution
It's not perfectly word-size independent, but one can extend the solution above to work for 16, 32 and 64 bit ints (although still depending on two's complement representation). The code is careful to not shift more than 15 bits at a time (otherwise the result is undefined behavior if int
is 16 bits):
int is_zero(int x) {
int zero = (x^x);
int one = ~(~zero + ~zero);
int four = one + one + one + one;
int k15 = (one << four) + ~zero;
return ~((x >> k15 >> k15 >> k15 >> k15 >> k15) |
((~x + one) >> k15 >> k15 >> k15 >> k15 >> k15));
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…