Calculate abs(int) without branching
For this you need someone to teach it to you: if you made it yourself, then you are a very good Comp-Sci, and you should send your CV to Google ASAP. ;)
Without branching O_o?
Yes, without using any “if ( a < 0 )...
”. To do that, you need to refresh how Two’s Complement works, then come back.
What we really need to focus on is that, given a signed int A
, the negative of that number is: B = ~A + 1
. BUT, we are trying to calculate the Absolute Value, not the negative. So, something like:
RESULT =
(INPUT, if positive, or NEGATE_INPUT, if negative)
+
(0, if positive, or 1, if negative)
Does it makes sense to you? To me it didn’t for the first 10 minutes.
What do we need?
We need, given the integer in input, to calculate 2 values:
- A way to "optionally negate" the input
- A variable carrying
0
if the input is positive,1
otherwise </ul> ### Look what we have here: theXOR
Properties of XOR are:A ^ 0 = A
A ^ 1 = ~A
A ^ A = 0
A ^ B = B ^ A
(commutative)
0
if positive and1
if negative, we would have half hack done. ### Ladies and Gentleman, all shift please Now, let's see some shifting in action. If A is a Positive number, then: ```c A = INPUT >> 31 => 0x00000000 => 0 B = -A => -0x00000000 => 0 ``` While if A is a Negative number, then: ```c A = INPUT >> 31 => 0xFFFFFFFF => -1 B = -A => 0x00000001 => 1 ``` ## Putting all together So, this means that we can calculate the absolute value using the new variables we have produced, A and B. Here is how: ```c #includeint abs(const int value) { int A = value >> 31; // 0x00000000 if Positive, 0xFFFFFFFF if Negative int B = -A; // 0x00000000 if Positive, 0x00000001 if Negative return (value ^ A) + B; // value ^ A = value if Positive, value ^ A = ~value if Negative } int main(int argc, char** argv) { int input; // Check the Input if ( argc == 2 ) input = atoi(argv[1]); else return (1); printf("abs(%d) = %d\n\n", input, abs(input)); } ``` Who showed me this hack? eh eh eh! ;)