Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to take absolute value of INT_MIN

Tags:

c

I want to perform some arithmetic in unsigned, and need to take absolute value of negative int, something like

do_some_arithmetic_in_unsigned_mode(int some_signed_value)
{
   unsigned int magnitude;
   int negative;
   if(some_signed_value<0) {
       magnitude = 0 - some_signed_value;
       negative = 1;
    } else {
       magnitude = some_signed_value;
       negative = 0;
    }
   ...snip...
}

But INT_MIN might be problematic, 0 - INT_MIN is UB if performed in signed arithmetic. What is a standard/robust/safe/efficient way to do this in C?

EDIT:

If we know we are in 2-complement, maybe implicit cast and explicit bit ops would be standard? if possible, I'd like to avoid this assumption.

do_some_arithmetic_in_unsigned_mode(int some_signed_value)
{
   unsigned int magnitude=some_signed_value;
   int negative=some_signed_value<0;
   if (negative) {
       magnitude = (~magnitude) + 1;
    }
   ...snip...
}
like image 772
aka.nice Avatar asked Sep 01 '12 21:09

aka.nice


People also ask

What is the absolute value of int min?

These functions return the absolute value of number . Most computers use a two's complement integer representation, in which the absolute value of INT_MIN (the smallest possible int ) cannot be represented; thus, abs (INT_MIN) is not defined.

Why is int min bigger than int max?

It's because there is only one zero, not a +0 and a -0 like in ones-complement.


1 Answers

Conversion from signed to unsigned is well-defined: You get the corresponding representative modulo 2N. Therefore, the following will give you the correct absolute value of n:

int n = /* ... */;

unsigned int abs_n = n < 0 ? UINT_MAX - ((unsigned int)(n)) + 1U
                           : (unsigned int)(n);

Update: As @aka.nice suggests, we can actually replace UINT_MAX + 1U by 0U:

unsigned int abs_n = n < 0 ? -((unsigned int)(n))
                           : +((unsigned int)(n));
like image 126
Kerrek SB Avatar answered Oct 05 '22 02:10

Kerrek SB