Value of i for (i == -i && i != 0) to return true in Java

Solution 1:

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 ?).

Solution 2:

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."

Solution 3:

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.

Solution 4:

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.