Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Absolute value of INT_MIN [duplicate]

How could I extract the absolute value of INT_MIN without overflowing? See this code for the problem:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("INT_MAX: %d\n", INT_MAX);
    printf("INT_MIN: %d\n", INT_MIN);
    printf("abs(INT_MIN): %d\n", abs(INT_MIN));

    return 0;
}

Spits out the following

INT_MAX: 2147483647
INT_MIN: -2147483648
abs(INT_MIN): -2147483648

I need this for a check if an int value is greater than zero.

As for this question being a duplicate of Why the absolute value of the max negative integer -2147483648 is still -2147483648?, I have to disagree, since this is a HOW, not a WHY question.

like image 313
Morgan Wilde Avatar asked Mar 08 '14 11:03

Morgan Wilde


3 Answers

How about

printf ("abs(INT_MIN) = %ld", -((long int) INT_MIN));

Or if your long is not longer than an int:

printf ("abs(INT_MIN) = %lld", -((long long int) INT_MIN));

Or if you are prepared to accept that abs(INT_MIN) is always INT_MAX + 1:

printf ("abs(INT_MIN) = %u", ((unsigned int) INT_MAX ) + 1 );
like image 100
abligh Avatar answered Oct 16 '22 20:10

abligh


The %d conversion specifier in the format string of printf converts the corresponding argument to a signed decimal integer, which in this case, overflows for the int type. C standard specifically mentions that signed integer overflow is undefined behaviour. What you should do is to use %u in the format string. Also, you need to include the headers stdio.h and stdlib.h for the prototype of the functions printf and abs respectively.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// This solves the issue of using the standard abs() function
unsigned int absu(int value) {
    return (value < 0) ? -((unsigned int)value) : (unsigned int)value;
}

int main(void) {
    printf("INT_MAX: %d\n", INT_MAX);
    printf("INT_MIN: %d\n", INT_MIN);
    printf("absu(INT_MIN): %u\n", absu(INT_MIN));

    return 0;
}

This gives the output on my 32-bit machine:

INT_MAX: 2147483647
INT_MIN: -2147483648
absu(INT_MIN): 2147483648
like image 21
ajay Avatar answered Oct 16 '22 21:10

ajay


There is no portable way to extract the absolute value of the most negative number as an integer. The ISO C standard says (§6.2.6.2¶2):

Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M ≤ N ).

Notice it uses ≤, not <.

Since the sign bit in 2's complement has the value −(2M), and each value bit has a value that is a power of two between 1 and 2M-1, there is no way an unsigned integer on implementations where M=N can represent 2N, it can only represent up to 2N-1 = 1+2+...+2N-1.

like image 41
ninjalj Avatar answered Oct 16 '22 20:10

ninjalj