Why the absolute value of the max negative integer -2147483648 is still -2147483648?
Asked Answered
G

6

29

The result of abs(-2147483648) is -2147483648, isn't it? it seems unacceptable.

printf("abs(-2147483648): %d\n", abs(-2147483648));

output:

abs(-2147483648): -2147483648
Glary answered 28/6, 2012 at 10:51 Comment(7)
I believe this is undefined behavior. I don't have the C standard handy, so I cannot back it up.Cabbala
What do you expect it to be, given that abs(int) returns an int?Howlan
Latest draft of C11 says (7.21.6.1, about abs and friends) "If the result cannot be represented, the behavior is undefined"Cabbala
@PhilipKendall The absolute value can be a negative value?Glary
linux man page says (man 3 abs): Trying to take the absolute value of the most negative integer is not defined.Epistemology
You get the right value if int has more than 32 bits. But for 32 bit ints, what would you have it be, considering that 2147483648 cannot be represented in 32 bits?Aurify
@JimBalter technically it can not be represented in 31 bits. The sign bit is what's causing this behaviour.Coach
W
34

The standard says about abs():

The abs, labs, and llabs functions compute the absolute value of an integer j. If the result cannot be represented, the behavior is undefined.

And the result indeed cannot be represented because the 2's complement representation of signed integers isn't symmetric. Think about it... If you have 32 bits in an int, that gives you 232 distinct values from INT_MIN to INT_MAX. That's an even number of values. So, if there's only one 0, the number of values greater than 0 cannot be the same as the number of values less than 0. And so there's no positive counterpart to INT_MIN with a value of -INT_MIN.

So, what's unacceptable is calling abs(INT_MIN) on your platform.

Whereinto answered 28/6, 2012 at 13:30 Comment(0)
E
19

Negative numbers are usually represented whit binary complement.

To convert positive to negative it is used logic

x -> not(x)+1

For 8 bits arithmetic

01111111b is 127 and -127 becomes
10000000b + 1 = 10000001b

and to opposite direction -127 10000001b becomes
01111110b + 1 = 01111111b

What about -128?

-128 is 10000000b and there is no positive counterpart of it, because there is no 128 in 8 bits signed arithmetic.

10000000 -> 01111111 + 1 = 10000000 and -128 again

Same applies to original question

Ermines answered 28/6, 2012 at 14:23 Comment(1)
that's why 0 and the minimum value are always the same after negating in two's complementMassa
C
11

Since 2147483648 is greater than INT_MAX on your implementation, then abs(-2147483648) is undefined.

Cabbala answered 28/6, 2012 at 11:17 Comment(0)
P
5

This is code in abs.c in GNU glibc source code.

/* Return the absolute value of I.  */
int
DEFUN(abs, (i), int i)
{
  return(i < 0 ? -i : i);
}

So,abs(-2147483648) return -(-2147483648) . In x86,it is implement by this two instruction

movl    $-2147483648, %eax
negl    %eax

negl instruction is implemented by this way: num=0-num; sbb is implemented by this way: Subtracts the source from the destination, and subtracts 1 extra if the Carry Flag is set. So abs(-2147483648) (hex is 0x80000000 ) --> -(-2147483648) --> 0-(-2147483648) becomes (0x80000000) finally.

details of negl instruction,please visit http://zsmith.co/intel_n.html#neg

details of sbb instruction ,please visit http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

Power answered 28/6, 2012 at 13:14 Comment(0)
F
1

I recall that this is an overflow error. The maximum value of an integer in S2C for signed integers is -(2^(total bits - 1)). However the maximum positive value is actually (2^(total bits - 1))-1. Bitwise, the function produces the right thing. However, the "correct" bitwise value overshoots the maximum positive value by one, rolling over to the set of negative values.

Frequentation answered 2/11, 2023 at 13:14 Comment(1)
This may be what happens for some implementations, but the Standard says that it is undefined behavior. Before C23 integers could be represented as two's complement, one's complement, or sign and magnitude. But even in C23 where only two's complement is allowed, it is still undefined behavior to attempt abs(INT_MIN).Slashing
I
-4

Try this

printf("abs(-2147483648): %u\n", abs(-2147483648));
Ingmar answered 28/6, 2012 at 11:10 Comment(2)
This, my friend, has undefined behavior. You're printing a signed integer with the unsigned formatter. I -1 because it moreover does not answer the question.Cabbala
The question is asking for explaining, not the way to fix the code.Eyelash

© 2022 - 2024 — McMap. All rights reserved.