why this code returns wrong value?
int i=Integer.MAX_VALUE+1;
long l=Integer.MAX_VALUE+1;
System.out.println(l);
System.out.println(i);
When you add 1 to Integer.MAX_VALUE it overflows and wraps around to Integer.MIN_VALUE.
This happens because Java uses two's complement to represent integers. An example in 4 bits:
0000 : 0
0001 : 1
...
0111 : 7 (max value)
1000 : -8 (min value)
...
1110 : -2
1111 : -1
So when you add 1 to 0111 (max) it goes to 1000, and that's the minimum. Expand this idea to 32-bits and it works the same way.
As for why your long is also showing an incorrect result, it's because it's performing addition on int s and then implicitly converting to long. You need to do:
long l = (long) Integer.MAX_VALUE + 1
System.out.println(l); // now prints the correct value
As the name says Integer.MAX_VALUE is the max value available for an Integer. In java when an Integer goes over its max value by 1 (or overflows by 1) then its value will be Integer.MIN_VALUE.
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.
Beware, with Float or Double you won't have this overflow, the value will be POSITIVE_INFINITY
An operation that overflows produces a signed infinity, an operation that underflows produces a denormalized value or a signed zero, and an operation that has no mathematically definite result produces NaN.
Resources :
JLS - MIN_VALUE & MAX_VALUE
Additive Operators (+ and -) for Numeric Types
You are overflowing the 32 bit integer type here by trying to store a value that cannot be represented by this type (2^31 - 1):
int i = Integer.MAX_VALUE + 1;
Java integer is 32 bit signed type ranges from: -2,147,483,648 to 2,147,483,647.
You can't set i integer variable as you did in i=Integer.MAX_VALUE+1;
Related
I've read about overflow, I know that "Overflow is when a number is so large that it will no longer fit within the data type, so the system “wraps around” to the next lowest value and counts up from there".
For example:
short s = (short)1921222; // Stored as 20678
In that example we started counting from -32768 (Short.MIN_VALUE), but when I try to prove in another integer data types, it doesn't seem work the same way...
byte b = (byte)400; // Stored as -112
The example above started counting from 0 that was the only way I found to get -112
I don't know if I am doing something wrong.
The Java Language Specification says:
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, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units.
So, short and byte are both two's complement integers.
short is 16 bits, meaning it can hold 2^16 = 65536 different values. After the 65536th value, it overflows.
1921222 modulo 65536 is 20678 . This is less than 32768 (2^15, the turning point for the two's complement) so we keep a positive number.
byte is 8 bits, meaning it can hold 2^8 = 256 different values. This one overflows after the 256hth value.
400 modulo 256 is 144. This value is higher than 128, the turning point for the two's complement - hence it will be interpreted as a negative two's complement number.
The cast is truncating the number. (JLS)
0000 0001 1001 0000
loses the high byte to become
1001 0000
which is -112.
In java, byte primitive type is an 8 bit signed integer, that's why you got -112 from calling:
byte b = (byte) 400;
You can avoid that and get its un-signed value, by binary adding it with 0xFF like this:
int b = (byte) 400 & 0xFF;
For further details you can check:
Java Primitive data types Documentation.
How to Convert Int to Unsigned Byte and Back
In addition to the other answers, you can get to that answer by manual calculation as well.
In Java, the data type byte is an 8-bit, signed integer. So the values are in the interval [-128, 127]. If you have a value of 400 and you want to see the actual value for that type, you can subtract the size of the interval from that number until you reach a value that's inside the interval.
As I said, byte is 8 bit, so the size of the interval is 256. Subtract that from your initial value: 400 - 256 = 144. This value is still outside of the interval so you have to subtract again: 144 - 256 = -112. This value is now inside the interval and is indeed the value you've seen in your test.
The same is true for your first example: short is 16 bit and signed, so the interval is [-32768, 32767] with size 65536. Doing repeated subtraction from the value 1921222 will eventually give you the value 20678 as seen in your test.
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)
System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);
is true.
I understand that integer in Java is 32 bit and can't go above 231-1, but I can't understand why adding 1 to its MAX_VALUE results in MIN_VALUE and not in some kind of exception. Not mentioning something like transparent conversion to a bigger type, like Ruby does.
Is this behavior specified somewhere? Can I rely on it?
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.
The integer storage gets overflowed and that is not indicated in any way, as stated in JSL 3rd Ed.:
The built-in integer operators do not indicate overflow or underflow in any way. Integer operators can throw a NullPointerException if unboxing conversion (§5.1.8) of a null reference is required. Other than that, the only integer operators that can throw an exception (§11) are the integer divide operator / (§15.17.2) and the integer remainder operator % (§15.17.3), which throw an ArithmeticException if the right-hand operand is zero, and the increment and decrement operators ++(§15.15.1, §15.15.2) and --(§15.14.3, §15.14.2), which can throw an OutOfMemoryError if boxing conversion (§5.1.7) is required and there is not sufficient memory available to perform the conversion.
Example in a 4-bits storage:
MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)
MAX_INT + 1:
0111+
0001
----
1000
You must understand how integer values are represented in binary form, and how binary addition works. Java uses a representation called two's complement, in which the first bit of the number represents its sign. Whenever you add 1 to the largest java Integer, which has a bit sign of 0, then its bit sign becomes 1 and the number becomes negative.
This links explains with more details: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java
--
The Java Language Specification treats this behavior here: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#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.
Which means that you can rely on this behavior.
On most processors, the arithmetic instructions have no mode to fault on an overflow. They set a flag that must be checked. That's an extra instruction so probably slower. In order for the language implementations to be as fast as possible, the languages are frequently specified to ignore the error and continue. For Java the behaviour is specified in the JLS. For C, the language does not specify the behaviour, but modern processors will behave as Java.
I believe there are proposals for (awkward) Java SE 8 libraries to throw on overflow, as well as unsigned operations. A behaviour, I believe popular in the DSP world, is clamp the values at the maximums, so Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [not Java].
I'm sure future languages will use arbitrary precision ints, but not for a while yet. Requires more expensive compiler design to run quickly.
The same reason why the date changes when you cross the international date line: there's a discontinuity there. It's built into the nature of binary addition.
This is a well known issue related to the fact that Integers are represented as two's complement down at the binary layer. When you add 1 to the max value of a two's complement number you get the min value. Honestly, all integers behaved this way before java existed, and changing this behavior for the Java language would have added more overhead to integer math, and confused programmers coming from other languages.
When you add 3 (in binary 11) to 1 (in binary 1), you must change to 0 (in binary 0) all binary 1 starting from the right, until you got 0, which you should change to 1. Integer.MAX_VALUE has all places filled up with 1 so there remain only 0s.
Easy to understand with byte example=>
byte a=127;//max value for byte
byte b=1;
byte c=(byte) (a+b);//assigns -128
System.out.println(c);//prints -128
Here we are forcing addition and casting it to be treated as byte.
So what will happen is that when we reach 127 (largest possible value for a byte) and we add plus 1 then the value flips (as shown in image) from 127 and it becomes -128.
The value starts circling around the type.
Same is for integer.
Also integer + integer stays integer ( unlike byte + byte which gets converted to int [unless casted forcefully as above]).
int int1=Integer.MAX_VALUE+1;
System.out.println(int1); //prints -2147483648
System.out.println(Integer.MIN_VALUE); //prints -2147483648
//below prints 128 as converted to int as not forced with casting
System.out.println(Byte.MAX_VALUE+1);
Cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483647, -2147483646, -2147483645, ... and so forth to the far most right again and on and on, its nature of summing machine on this bit depth.
Some examples:
int a = 2147483647;
System.out.println(a);
gives: 2147483647
System.out.println(a+1);
gives: -2147483648 (cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483648, -2147483647, -2147483646, ... and so fores to the far most right again and on and on, its nature of summing machine on this bit depth)
System.out.println(2-a);
gives:-2147483645 (-2147483647+2 seems mathematical logical)
System.out.println(-2-a);
gives: 2147483647 (-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 some loop described in previous answers)
System.out.println(2*a);
gives: -2 (2147483647+2147483647 -> -2147483648+2147483646 again mathematical logical)
System.out.println(4*a);
gives: -4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647 -> -2-2 (according to last answer) -> -4)`