35

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?

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
  • plenty of good answers here now, however I'm now curious about why you ask "Can I rely on it?" - why would you want to rely on it? – Brian Feb 22 '12 at 15:30
  • it could be another question, --- I was looking for some 'iterator' that would iterate an array starting from element N, then after reaching the end element start iterating from element 0 to element N-1 --- and this Integer behavior could be useful for that... but i ended up with just two different loops – Oleg Mikheev Feb 22 '12 at 15:51
  • 3
    For reference, if you want to get an exception instead, some libraries provide methods: [Guava](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedAdd(int,%20int)) [Apache](http://commons.apache.org/math/api-2.2/org/apache/commons/math/util/MathUtils.html#addAndCheck(int,%20int)) – Louis Wasserman Feb 22 '12 at 18:53
  • Whats even more confusing is why inversion of INT min value is still negative! `int b = -Integer.MIN_VALUE;` !! 2's complement math is so confusing. – djangofan Dec 04 '16 at 19:11
  • 2
    All these answers, all addressing how int works, none of them answering the question: Why does it do that? Why doesn't it throw an exception? Is there some useful functionality gained by allowing Integer.MAX_VALUE + 1 == -2147483648? – bobanahalf Oct 17 '18 at 11:26

9 Answers9

36

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.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
29

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
falsarella
  • 12,217
  • 9
  • 69
  • 115
  • 1
    All these answers, all addressing how int works, none of them answering the question: Why does it do that? Why doesn't it throw an exception? Is there some useful functionality gained by allowing Integer.MAX_VALUE + 1 == -2147483648? – bobanahalf Oct 17 '18 at 11:27
8

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.

falsarella
  • 12,217
  • 9
  • 69
  • 115
ARRG
  • 2,476
  • 17
  • 28
7

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.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
4

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.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • It is true that there is a discontinuity (or to put it another way, bounds on the range of `int`) and that this must be handled some way. But it does not follow that it *must* be handled this way. There are a number of of other ways to handle integer overflow ... at least in theory. – Stephen C Apr 15 '21 at 00:37
3

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.

Craig H
  • 7,949
  • 16
  • 49
  • 61
2

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.

IProblemFactory
  • 9,551
  • 8
  • 50
  • 66
1

Easy to understand with byte example=> enter image description here

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);
Chirag
  • 1,478
  • 16
  • 20
  • The stuff about adding `byte` arithmetic is a bit misleading ... and not really relevant. Since `byte` values are always promoted to `int` (or a "larger" type) before performing any arithmetical operations on them, it doesn't help to talk about examples involving `byte` to understand integer overflow behavior. – Stephen C Apr 15 '21 at 00:31
-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)`

Oleg Kamuz
  • 29
  • 3