We take a simple code:

void main() { int x = abs(-1); } 

We assemble and disassemble it:

 $ gcc sample.c -o sample && objdump -d ./sample 

We get a listing where there is no conditional command:

 80483a1: e8 ee ff ff ff call 8048394 <some> 80483a6: 89 c2 mov %eax,%edx 80483a8: c1 fa 1f sar $0x1f,%edx 80483ab: 31 d0 xor %edx,%eax 80483ad: 29 d0 sub %edx,%eax 

How in C / C ++ to get the absolute value of an integer without a comparison operation?

    4 answers 4

    The sar assembler operation is a normal shift to the right. Here is your code:

     int myabs(int x) { //mov %eax,%edx //sar $0x1f,%edx int minus_flag = x>>0x1F;//0x1F = 31 //xor %edx,%eax int y = minus_flag ^ x; //sub %edx,%eax y -=minus_flag; return y; } 
    • one
      taken - stanislav

    I'd rather be Java oriented, so in order not to look stupid, I won't write code in C :) But from an algorithmic point of view, it should look something like this:

    (I suppose, in C / C ++, the representation of a signed integer is made using additional code )

    1. Copy somewhere the first bit.
    2. Create a new integer variable of the same size.
    3. Copy to all bits of the second number the value of the previously saved bit.
    4. Apply the bitwise exclusive or first number to the second (XOR).
    5. Add to the resulting number the value of the previously stored bit.

    I will give a table of actions for the numbers -5 and 3 which are stored in 8 bits.

    number1 additional number1 additional bit number 1 additional number 2 additional bit 2

    1. 11111011 00000000 1 00000011 00000000 0
    2. 11111011 00000000 1 00000011 00000000 0
    3. 11111011 11111111 1 00000011 00000000 0
    4. 00000100 11111111 1 00000011 00000000 0
    5. 00000101 11111111 1 00000011 00000000 0

    The algorithm is not great, but it is not a comparison :)

      The first thing that came to mind immediately after reading the question was to take the square root of the square of a number:

       sqrt(x*x) 

      Another option is, as already noted here, to take advantage of the knowledge of number representation and additional code and bitwise operations.

      Example for 8-bit numbers

       char x = -5; char minus = (x & 0x80) >> 7; // равно 1 если x - отрицательное и 0 если положительное char plus = (((x & 0x80) >> 7) + 1) & 1; // наоборот, равно 1, если x - положительное, и 0 если отрицательное char abs_x = minus * (-x) + plus * x; 

      For int it will be more difficult, since You will need to take into account a bunch of features, for example, the bit width (int can be 8, 16, 32, 64-bit) and the byte order (Little-Endian / Big-Endian).

      • Do not forget how the root is calculated, which at least will contain a check for non-negativity, multiplication in the problem of bit arithmetic is also not appropriate - Singlet

      The algorithmic trick on which the calculation of the module without branching is based is the property of the additional code. The xor operation with the number -1 causes the bits of the number to be inverted, and the addition of 1 completes the transition to the negation of the number. Moreover, the number -1 itself is obtained as a sign shift to the right of the original number, if it was negative. If the number was positive, the shift will give 0, so xor and sub will not change anything. More information about similar algorithms for calculating the module and the speed of their work can be found here .