Why Integer.Max_Value + 1 == Integer.Min_Value

why Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

Because the integer overflows. When it overflows, the next value is Integer.MIN_VALUE. Relevant JLS

If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.

Integer.MIN_VALUE divide by -1

Java use 32 bit to store int.

The max int value is 231-1

0111 1111 1111 1111 1111 1111 1111 1111

The min int value is -231

1000 0000 0000 0000 0000 0000 0000 0000

In other words, int does not have a big enough value to store 231(-Integer.MIN_VALUE).

Why does the negative of Integer.MIN_VALUE give the same value?

What kind of bit-wise operations are happening internally?

Java uses two's complement representation of signed numbers. Therefore, the change of sign operation, consists of two steps:

  1. Inverting the bits of the original value, and
  2. Adding 1 to the result.

2147483648's representation is shown below:

10000000000000000000000000000000

Inverting it produces

01111111111111111111111111111111

Adding 1 makes it the same number again, i.e.

10000000000000000000000000000000

due to integer overflow.

Reproduce behavior MAX_VALUE and MIN_VALUE

Here's one without bitwise operations (I'm not counting the constant-generation, they could be written out but it would obscure their meaning) or casts, as you can see it's more complicated than it should be, and it would be worse without Java 8:

long reproduceMinMaxFromLongToInt(long n){
// reduce range
n = Long.remainderUnsigned(n, 1L << 32);
// sign-extend
if (n < (1L << 31))
return n;
else
return n - (1L << 32);
}

Implementing other pairs of min/max this way is probably a strange thing to do. A more reasonable approach, probably, is to work only with positive numbers (in Java) modulo the length of the range, and interpret the upper range of them as being negative.

For example if the range was -2 through 2, you could bring them all into 0..4 by mapping them modulo (actual modulo, not Java-style remainder) 5. Then the usual mod-5 arithmetic will act reasonably. In the end just map them back to the original range, by interpreting 4 as -1 (which is, in mod-5 arithmetic, a reasonable thing to say) and 3 as -2.

You could interpret the code above as doing that, but there is the weird issue that (due to the range involved) it had to work with signed numbers as if they were unsigned, so Long.remainderUnsigned made an appearance. For small ranges that wouldn't be a problem.

Explanation on Integer.MAX_VALUE and Integer.MIN_VALUE to find min and max value in an array

but as for this method, I don't understand the purpose of Integer.MAX_VALUE and Integer.MIN_VALUE.

By starting out with smallest set to Integer.MAX_VALUE and largest set to Integer.MIN_VALUE, they don't have to worry later about the special case where smallest and largest don't have a value yet. If the data I'm looking through has a 10 as the first value, then numbers[i]<smallest will be true (because 10 is < Integer.MAX_VALUE) and we'll update smallest to be 10. Similarly, numbers[i]>largest will be true because 10 is > Integer.MIN_VALUE and we'll update largest. And so on.

Of course, when doing this, you must ensure that you have at least one value in the data you're looking at. Otherwise, you end up with apocryphal numbers in smallest and largest.


Note the point Onome Sotu makes in the comments:

...if the first item in the array is larger than the rest, then the largest item will always be Integer.MIN_VALUE because of the else-if statement.

Which is true; here's a simpler example demonstrating the problem (live copy):

public class Example
{
public static void main(String[] args) throws Exception {
int[] values = {5, 1, 2};
int smallest = Integer.MAX_VALUE;
int largest = Integer.MIN_VALUE;
for (int value : values) {
if (value < smallest) {
smallest = value;
} else if (value > largest) {
largest = value;
}
}
System.out.println(smallest + ", " + largest); // 1, 2 -- WRONG
}
}

To fix it, either:

  1. Don't use else, or

  2. Start with smallest and largest equal to the first element, and then loop the remaining elements, keeping the else if.

Here's an example of that second one (live copy):

public class Example
{
public static void main(String[] args) throws Exception {
int[] values = {5, 1, 2};
int smallest = values[0];
int largest = values[0];
for (int n = 1; n < values.length; ++n) {
int value = values[n];
if (value < smallest) {
smallest = value;
} else if (value > largest) {
largest = value;
}
}
System.out.println(smallest + ", " + largest); // 1, 5
}
}

Why Integer.MIN_VALUE is -2^32 while Integer.MAX_VALUE is 2^31-1?

Consider a simple 4 bit scenario:

Computer stores negative integers as 2's complement. To get a 2's complement of number we follow this procedure:

for negative 8=>
1000 (positive 8 in binary)

0111 (flip all bits=1's complement)

+ 1 (add 1)


1000 (this is how negative 8 as integer is stored in the computer, MSB=sign bit=1 indicates -ve)

therefore 2's complement=1's complement+1

1 advantage of 2's complement is that it has only 1 representation of 0 unlike 1's complement(which has +ve and -ve 0 i.e 0000 and 1111 respectively called as 0 crossing problem). Hence that is the reason you get an extra value in the negative side

so to conclude for a 4 bit scenario:

  • 0000 to 0111 means 0 to +ve 7 (MSB used as sign bit, MSB=0 means
    +ve)
  • 1000 to 1111 means -8 to -1(MSB=1 means -ve)
  • 0 in 2's complement is 0000, 2's complement: 0000->1111+1=10000(extra
    carry 1 is out of range hence it results 000) i.e only 1
    representation for 0 i.e 0000

to count: 0 to 7 is 2^3-1=7 +ve

to count: -8 to -1 is 2^3=8 -ve

to count: count for 0 is 1

Sum of the counts=> 1+7+8=16=2^4

Therefore for your question: 2^31 are +ve integers and 2^31-1 are -ve integers and 1 more value for 0.

Sidenote:

converting from 2's complement: 1000->0111+1=1000(8)

value is 8 and put a -ve sign i.e final value is -8

converting from 2's complement: 1111->0000+1=0001(1)

value is 1 and put a -ve sign i.e final value is -1

since Integer.MAX_VALUE+1==Integer.MIN_VALUE+1, how long will this loop run(sounds like a dumb question but its not)?

It won't loop at all.

You initialize x = 0 and then check x != 0. So loop will ends immediately.

If you initialize x = 1 then you get "2^32-1" iterations.

Why does Integer.MAX_VALUE*2 returns -2?

That's because Java's signed integers follow two's complement representation.

In a two's complement representation, negative numbers are represented as an N-bit complement of their corresponding positive value, i.e. their sum modulo 2n is 0.

Integer.MAX_VALUE is 2147483647 (hex 0x7FFFFFFF).
When multiplied, it overflows, and what remains is the lowest 32 bits (i.e. modulo 232):

0x7FFFFFFF * 2 = 0x0FFFFFFFE (mod32 = 0xFFFFFFFE = -2)
0x7FFFFFFF * 3 = 0x17FFFFFFD (mod32 = 0x7FFFFFFD = 2147483645)
0x7FFFFFFF * 4 = 0x1FFFFFFFC (mod32 = 0xFFFFFFFC = -4)
0x7FFFFFFF * 5 = 0x27FFFFFFB (mod32 = 0x7FFFFFFB = 2147483643)
0x7FFFFFFF * 6 = 0x2FFFFFFFA (mod32 = 0xFFFFFFFA = -6)
0x7FFFFFFF * 7 = 0x37FFFFFF9 (mod32 = 0x7FFFFFF9 = 2147483641)

An interesting property of two's complement representation is that the highest bit corresponds to the sign of the value.

Notice how the leftmost 7 results in alternating 0/1 bit 31. That bit happens to control the sign of the result, hence the alternating sign.

Why 0x7FFFFFFF * 2 is -2 is because 0x7FFFFFFF in a 31-bit representation (the largest possible representation without overflowing) is -1. And -1 * 2 = -2.

You can achieve a similar result if you take Long.MAX_VALUE and cast the result to int:

long x = Long.MAX_VALUE;
for (int i = 2; i < 8; i++) {
System.out.println((int)(x * i));
}

Just prints:

-2
-3
-4
-5
-6
-7

Now bit 31 isn't alternating anymore so we get stable results.



Related Topics



Leave a reply



Submit