101

I have the following if condition.

if (i == -i && i != 0)

What value of i will return true for this condition in Java?

I am unable to think of any such value of i considering two's complement notation in Java.

I would also love to have algebraic proof of whatever answer this condition has (in context with Java)?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sunny
  • 1,441
  • 2
  • 13
  • 22

6 Answers6

126

The only int value for which it works is Integer.MIN_VALUE.

It's because integers are negated using the two's complement way.

Using

System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));

you see that Integer.MIN_VALUE is

10000000000000000000000000000000

Taking the negative value is done by first swapping 0 and 1, which gives

01111111111111111111111111111111

and by adding 1, which gives

10000000000000000000000000000000

As you can see in the link I gave, Wikipedia mentions the problem with the most negative numbers and specifies it's the sole exception :

The most negative number in two's complement is sometimes called "the weird number," because it is the only exception.

Of course you have the same phenomenon for Long.Min_Value if you store it in a long variable.

Note that this is only due to choices that were made regarding the binary storage of ints in Java. Another (bad) solution could for example have been to negate by simply changing the most significant bit and letting the other bits unchanged, this would have avoided this problem with MIN_VALUE but would have made 2 different 0 values and complicated binary arithmetic (how would you have incremented for example ?).

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 2
    It's worth noting that early binary computers did use the sign and magnitude implementation for integers described in your last paragraph; as do IEE754 floating point numbers. http://en.wikipedia.org/wiki/Signed_number_representations#Sign-and-magnitude_method – Dan Is Fiddling By Firelight Jul 22 '13 at 21:05
  • 1
    Re: "this is only related to choices that were made regarding the binary storage of ints": And the choices of how to handle overflow. The rule that Java uses is not the same as the rule used by (say) C or the rule used by (say) Standard ML, even though all of these run on wide varieties of systems. – ruakh Jul 22 '13 at 22:27
  • 2
    Worth mentioning that it is [documented on the Java Spec](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.4): "The Java programming language uses two's-complement representation for integers, and the range of two's-complement values is not symmetric, so negation of the maximum negative int or long results in that same maximum negative number." – chesterbr Jul 26 '13 at 04:11
25

The value you are looking for is Integer.MIN_VALUE.


I would also love to have algebraic proof of whatever answer this condition has(in context with java)?

That's off-topic for Stack Exchange. But you could do it starting from the definition of Java integers (JLS 4.2)

"The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers ..."

and

"The values of the integral types are integers in the following ranges ... For int, from -2147483648 to 2147483647, inclusive"

and the definition of the Java unary '-' operator (JLS 15.15.4):

"For integer values, negation is the same as subtraction from zero. The Java programming language uses two's-complement representation for integers, and the range of two's-complement values is not symmetric, so negation of the maximum negative int or long results in that same maximum negative number. Overflow occurs in this case, but no exception is thrown. For all integer values x, -x equals (~x)+1."

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 3
    _Long.MIN_VALUE_ as well. – Juvanis Jul 22 '13 at 06:28
  • 1
    which is 100000.., and if i get 2's compliment of it, it is again 011111...+1 = 100000...but you know it top of your head or we can apply any logic? – Sunny Jul 22 '13 at 06:29
  • 1
    As i have read..java's int arithmetic is arithmetic mod 2power32, so i was thinking if we can prove this value in just 1 or 2 lines..if its a big proof..then no issue. – Sunny Jul 22 '13 at 06:35
  • 2
    @Sunny it can't be too hard to prove. In the integer range, all positive numbers have a negative counterpart (so `i != -i`) . That leaves two numbers in the range: `0` and `Integer.MIN_VALUE`. Because of `i != 0` in your if, only `MIN_VALUE` is left. – Vincent van der Weele Jul 22 '13 at 06:38
  • 1
    @Heuster - that reasoning works ... but it depends on an assumption or two that require proof. – Stephen C Jul 22 '13 at 22:35
18

In additional to the answers given so far...

There is four values in total

int i = Integer.MIN_VALUE;
long i = Long.MIN_VALUE;
Integer i = Integer.valueOf(Integer.MIN_VALUE);
Long i = Long.valueOf(Long.MIN_VALUE);

The wrapped values get unwrapped so they are also true for this expression.

Note: Math.abs documents.

public static int abs(int a)

Returns the absolute value of an int value. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.

Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.

and

public static long abs(long a)

Returns the absolute value of a long value. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.

Note that if the argument is equal to the value of Long.MIN_VALUE, the most negative representable long value, the result is that same value, which is negative.

It is surprising that Math.abs might return a negative number. This happens either because a) there is no positive values for -MIN_VALUE in these cases b) performing the - calculation results in an overflow.

What is also interest is why doesn't Byte.MIN_VALUE, Short.MIN_VALUE do not do this. This is because the - changes the type to int for these and thus no overflow.

Character.MIN_VALUE doesn't have a problem because it is 0.

Float.MIN_VALUE and Double.MIN_VALUE have a different meaning. These are the smallest representable value greater than zero. Thus they have valid negative values which are not themselves.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
14

Like the others have mentioned, this is only fulfilled by Integer.MIN_VALUE. As for proof, let me offer an easier to understand explanation other than in binary (although it is still rooted in that).

Note that Integer.MIN_VALUE is equal to -2^31 or -2147483648 and Integer.MAX_VALUE is equal to 2^31-1 or 2147483647. -Integer.MIN_VALUE is 2^31, which is now too large for an Integer (since it is past MAX_VALUE) thus causing an Integer overflow, making it Integer.MIN_VALUE again. It's the only Integer that does this since MIN_VALUE is the only number with no negative equivalent aside from 0.

Mark M
  • 1,580
  • 10
  • 22
  • 2
    @dystroy actually i was looking for some explanation, acc to Mark, there is no such number as +2147483648 in int range, so first suspect should be this number other than 0. Range is -2^n to 2^n-1. So there is no positive counterpart to -2^n. This is only another possible int value. – Sunny Jul 22 '13 at 08:40
  • 1
    I didn't explain in binary since it was already covered by someone else (basically int is a 32-bit value that's why it has those limits). Also, negative of negative is positive, so the terms can still apply. – Mark M Jul 22 '13 at 09:06
  • 1
    Oddly enough in Java, the number `2147483648` may appear in source code only in one circumstance: as the operand of the unary minus operator (JLS 3.10.1). – Eric Jablow Jul 24 '13 at 00:03
6

Tentative algebraic proof, using modulo 2^32 arithmetic:

i == -i can be rewritten as 2 * i == 0 (adding i on both sides), or i << 1 == 0.

This equation has two solutions of the form i == 0 >> 1, namely 0b and 10000000000000000000000000000000b obtained by shifting in either 0 or 1 on the left.

The solution i == 0 being excluded, there remains the solution i == 100000000000000000000000000000000b.

0

Maybe it's not too educative, but instead of thinking you could run this code:

    for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
    {
        if (i == -i && i != 0)
        {
            System.out.println(i);
        }
    }

to see that it prints

-2147483648
-2147483648

infinitely :)

Kuba
  • 2,986
  • 2
  • 26
  • 32