Can someone provide me with a detailed explanation of why 2,147,483,647 is the maximum integer value in Java?
Because the total value an int can hold in Java is 2^32 (2 to the power of 32, in other words a 32 bit number), for which half is reserved for negative numbers and half for positive numbers.
Related
This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 3 years ago.
I'm wondering why java int type (32 bit signed) has valid value in range -2,147,483,648 to 2,147,483,647 but not in (-2,147,483,648 to 2,147,483,648)?
The primary representation of numbers in modern computers is some form of binary representation. It consists of a fixed number of bits that take the values 0 or 1. In Java, an int is specified to use a binary representation with 32 bits.
A 32 bit binary representation can have 2^32 states. (This is a mathematical fact. It can be proven from first principles.)
Consider the mathematical integers from -2^31 to +2^31:
There are 2^31 numbers in the range 1 to 2^31 (inclusive)
There are 2^31 numbers in the range -1 down to -(2^31) (inclusive)
The value zero is not in either of the above ranges.
So counting the numbers from -2^31 to +2^31, we get a total of 2^31 + 2^31 + 1 values. That is 2^32 + 1 which is more values than can be represented in 2^32 states.
What you are suggesting is not mathematically possible.
This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 4 years ago.
If Java's long primitive data type is a 64-bit signed integer, then why do the Java docs state that the static long maximum value is 2^63-1? Is there a larger reason that affects other primitive data types similarly in Java?
I'm learning Java and am just genuinely curious about this disparity. Thank you.
Java's long type is indeed a 64-bit integer, but it is also signed.
With 64-bit, you can represent 2^64 different numbers. If you ignore all the negative numbers, then the maximum value would be 2^64-1, and minimum will be 0. 0 plus all 2^64-1 positive numbers is 2^64 numbers in total.
However, if you consider all the negative numbers as well as the positives, about half of the 2^64 different numbers will be negative. Java just chose to represent 2^63 negative numbers, the number 0, and 2^63-1 positive numbers. If you add all these up, you get 2^64 total numbers.
2^63 + 1 + 2^63 - 1 = 2^64
^
|
this is the number zero
Its just a range formula just like range for octal and hexadecimal numbers 2^n -1
different for signed and unsigned numbers. 2^n and 2^n-1(Range)
I have a test tomorrow and I can't understand my books explanation, I appreciate the help:
public class TestClass{
public static void main(String[] args) throws Exception{
int a = Integer.MIN_VALUE;
int b = -a;
System.out.println( a+ " "+b);
}
}
Output: -2147483648 -2147483648
Why does this print 2 negative numbers of the same magnitude and not a positive and negative?
Because of silent integer overflow: Integer.MIN_VALUE is -2^31 and Integer.MAX_VALUE is 2^31-1, so -Integer.MIN_VALUE is 2^31, which is Integer.MAX_VALUE + 1, which by definition is too large for an integer. So it overflows and becomes Integer.MIN_VALUE...
You can also check that:
System.out.println(Integer.MAX_VALUE + 1);
prints the same thing.
More technically, the result is defined by the Java Language Specification #15.18.2:
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.
Basically, because Integer.MAX_VALUE is actually only 2147483647, so -Integer.MIN_VALUE, which would be +2147483648, actually overflows the capacity of the internal binary representation of integers. Thus, the result "loops around" back to Integer.MIN_VALUE, or -2147483648.
If you did long b = -((long)a); instead, you would get the expected result.
To show this even more clearly:
Integer.MIN_VALUE is -2^31 = -2147483648
Integer.MAX_VALUE is 2^31-1 = 2147483647
/*notice this is 1 less than the negative value above*/
Integer.MAX_VALUE can not take 2147483648. This is too large number for Integer by exactly 1. This causes the number to go back on the scale from max value back to starting poing which is the min value.
A fixed number of binary bits can encode an even number of things. That means that you can't have a sequence that's exactly centered on zero, since that would require an is number of things to be symmetrical. The closest thing you can get to having zero in the middle of the sentence is to split it as either negative and non-negative, or positive and non-positive. Normal twos complement encoding does the former. So 32 bits span the range from -2^31 to 2^31-1. Zero is in the non-negative half of the sequence, and you have one negative number that can not be properly negated.
Java ints are stored in a 32-bit two's compliment form. Similar results applies for all two's compliment representations. The anomalous behavior is due to the extra negative integer which is an artifat of two's compliment.
-2147483748 has a leadbitwise representation of
10000000 00000000 00000000 00000000
and the negative of a number is achieved by flipping all the bits and adding one to it. The largest positive int will have a bitwise representation of
01111111 11111111 11111111 11111111
which is 2147483647. We then add one more, so bitwise, we have
10000000 00000000 00000000 00000000 == -2147483648
This extra integer is an artifact of the two's compliment representation and operations with this number can have undesirable consequences. -2147483748 is indeed unique among the ints!
I have a test tomorrow and I can't understand my books explanation, I appreciate the help:
public class TestClass{
public static void main(String[] args) throws Exception{
int a = Integer.MIN_VALUE;
int b = -a;
System.out.println( a+ " "+b);
}
}
Output: -2147483648 -2147483648
Why does this print 2 negative numbers of the same magnitude and not a positive and negative?
Because of silent integer overflow: Integer.MIN_VALUE is -2^31 and Integer.MAX_VALUE is 2^31-1, so -Integer.MIN_VALUE is 2^31, which is Integer.MAX_VALUE + 1, which by definition is too large for an integer. So it overflows and becomes Integer.MIN_VALUE...
You can also check that:
System.out.println(Integer.MAX_VALUE + 1);
prints the same thing.
More technically, the result is defined by the Java Language Specification #15.18.2:
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.
Basically, because Integer.MAX_VALUE is actually only 2147483647, so -Integer.MIN_VALUE, which would be +2147483648, actually overflows the capacity of the internal binary representation of integers. Thus, the result "loops around" back to Integer.MIN_VALUE, or -2147483648.
If you did long b = -((long)a); instead, you would get the expected result.
To show this even more clearly:
Integer.MIN_VALUE is -2^31 = -2147483648
Integer.MAX_VALUE is 2^31-1 = 2147483647
/*notice this is 1 less than the negative value above*/
Integer.MAX_VALUE can not take 2147483648. This is too large number for Integer by exactly 1. This causes the number to go back on the scale from max value back to starting poing which is the min value.
A fixed number of binary bits can encode an even number of things. That means that you can't have a sequence that's exactly centered on zero, since that would require an is number of things to be symmetrical. The closest thing you can get to having zero in the middle of the sentence is to split it as either negative and non-negative, or positive and non-positive. Normal twos complement encoding does the former. So 32 bits span the range from -2^31 to 2^31-1. Zero is in the non-negative half of the sequence, and you have one negative number that can not be properly negated.
Java ints are stored in a 32-bit two's compliment form. Similar results applies for all two's compliment representations. The anomalous behavior is due to the extra negative integer which is an artifat of two's compliment.
-2147483748 has a leadbitwise representation of
10000000 00000000 00000000 00000000
and the negative of a number is achieved by flipping all the bits and adding one to it. The largest positive int will have a bitwise representation of
01111111 11111111 11111111 11111111
which is 2147483647. We then add one more, so bitwise, we have
10000000 00000000 00000000 00000000 == -2147483648
This extra integer is an artifact of the two's compliment representation and operations with this number can have undesirable consequences. -2147483748 is indeed unique among the ints!
I was trying to check different inputs and creating infinite loops in java and I found that once the int is getting incremented over the maximum limit it turns in to negative -2147482958. I am just increasing the int in infinite loop...
Code:
public static void infiniteLoop(){
for(int i=0;i>-1;i++){
i = i + 1000;
System.out.println(i);
}
}
The last to value gets printed out is,
2147483337
-2147482958
Now, Why does it goes to negative?
Why does it goes to negative?
Because that is what is specified to happen in Java when an int calculation overflows.
JLS 15.18.2
"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."
(This doesn't explicitly say that overflow always gives a negative number. And it doesn't always. But if you apply the rule, it does explain why incrementing Integer.MAX_VALUE by +1 gives you Integer.MIN_VALUE ...)
According to the documentation:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 (0x80000000) and a maximum value of 2,147,483,647 (0x7FFFFFFF) (inclusive)
So when you add one to an integer's max value:
0x7FFFFFFF + 0x00000001 = 0x80000000 (-2,147,483,648)
Because when the value of an int reaches Integer.MAX_VALUE, incrementing it causes overflow and hence wraps around to Integer.MIN_VALUE.
To use larger integers, use a long instead which has 64 bits.
Because int ranges from -2,147,483,648 to 2,147,483,647. Hence,once it reaches it upper limit, it overflows and starts from the negative.
See the docs:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive)