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:
- Inverting the bits of the original value, and
- 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:
Don't use
else
, orStart with
smallest
andlargest
equal to the first element, and then loop the remaining elements, keeping theelse 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
How to Merge Documents Correctly
No Tests Found with Test Runner 'Junit 4'
How to Draw a Decent Looking Circle in Java
Spring 3 MVC: One-To-Many Within a Dynamic Form (Add/Remove on Create/Update)
Reset Buffer with Bufferedreader in Java
Java Stanford Nlp: Part of Speech Labels
How to Set Connection Timeout with Okhttp
Java.Lang.Nosuchmethoderror in Flink
Javafx: "Toolkit" Not Initialized When Trying to Play an Mp3 File Through Mediaplayer Class
How Do Determine If an Object Is Locked (Synchronized) So Not to Block in Java
How to Make Cartesian Product with Java 8 Streams
What Is the Jvm Thread Scheduling Algorithm
Can a Private Method in Super Class Be Overridden in the Sub-Class