58

In Java, what happens when you increment an int (or byte/short/long) beyond it's max value? Does it wrap around to the max negative value?

Does AtomicInteger.getAndIncrement() also behave in the same manner?

0xCursor
  • 2,242
  • 4
  • 15
  • 33
Lyke
  • 4,575
  • 6
  • 27
  • 26
  • [This PDF](http://pages.cs.wisc.edu/~willb/cs302/spring-07/why-integer-overflow-cl.pdf) give a neat explanation of how/why it works. Yes, the atomic version will do the same thing. – TofuBeer Feb 27 '11 at 03:04

7 Answers7

72

From the Java Language Specification section on integer operations:

The built-in integer operators do not indicate overflow or underflow in any way.

The results are specified by the language and independent of the JVM version: Integer.MAX_VALUE + 1 == Integer.MIN_VALUE and Integer.MIN_VALUE - 1 == Integer.MAX_VALUE. The same goes for the other integer types.

The atomic integer objects (AtomicInteger, AtomicLong, etc.) use the normal integer operators internally, so getAndDecrement(), etc. behave this way as well.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
14

If you do something like this:

int x = 2147483647;
x++;

If you now print out x, it will have the value -2147483648.

0xCursor
  • 2,242
  • 4
  • 15
  • 33
jterrace
  • 64,866
  • 22
  • 157
  • 202
  • 1
    What happens to x at the binary level when it is incremented? – Anfernee Apr 21 '16 at 01:02
  • 5
    `01111111111111111111111111111111` -> `10000000000000000000000000000000`. With [two's complement](https://en.wikipedia.org/wiki/Signed_number_representations#Two.27s_complement), the second number there is negative. – jterrace Apr 21 '16 at 15:38
  • so, 10000000000000000000000000000000 is equivalent to -2147483648, correct? – Anfernee Apr 21 '16 at 17:31
6

As jterrace says, the Java run-time will "wrap' the result to the Integer.MIN_VALUE of -2147483648.

But that is Mathematically incorrect! The correct Mathematically answer is 2147483648. But an 'int' can't have a value of 2147483648. The 'int' boundaries are -2147483648 to 2147483647

So why doesn't Java throw an exception? Good question! An Array object would.

But language authors know the scope of their primitive types, so they use the 'wrapping' technique to avoid a costly exception.

You, as a developer, must test for these type boundaries. A simple test for incrementing would be

if(x++ == Integer.MIN_VALUE)
   //boundary exceeded

A simple test for decrementing would be

if(x-- == Integer.MAX_VALUE)
   //boundary exceeded

A complete test for both would be

if(x++ == Integer.MIN_VALUE || x-- == Integer.MAX_VALUE)
   //boundary exceeded
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
GregJF
  • 456
  • 4
  • 14
  • 8
    In the last example, I think you can not use ++ and -- operators that way to check the boundaries as they are actually changing the value of x. Instead that should be refactored to something like if (x + 1 == Integer.MIN_VALUE || x - 1 == Integer.MAX_VALUE) – ronkot Feb 01 '16 at 12:38
  • 2
    Wait, why can't you just check if x == Integer.MAX_VALUE instead of x + 1 == Integer.MIN_VALUE? – jeffkmeng Jan 18 '20 at 09:30
4

What happens is an extra bit is added to the furthest right bit and the order decrements as a negatively signed int ... Notice what happens after 'int_32';

    int _0  = 0b0000000000000000000000000000000;
    int _1  = 0b0000000000000000000000000000001;
    int _2  = 0b0000000000000000000000000000010;
    int _3  = 0b0000000000000000000000000000100;
    int _4  = 0b0000000000000000000000000001000;
    int _5  = 0b0000000000000000000000000010000;
    int _6  = 0b0000000000000000000000000100000;
    int _7  = 0b0000000000000000000000001000000;
    int _8  = 0b0000000000000000000000010000000;
    int _9  = 0b0000000000000000000000100000000;
    int _10 = 0b0000000000000000000001000000000;
    int _11 = 0b0000000000000000000010000000000;
    int _12 = 0b0000000000000000000100000000000;
    int _13 = 0b0000000000000000001000000000000;
    int _14 = 0b0000000000000000010000000000000;
    int _15 = 0b0000000000000000100000000000000;
    int _16 = 0b0000000000000001000000000000000;
    int _17 = 0b0000000000000010000000000000000;
    int _18 = 0b0000000000000100000000000000000;
    int _19 = 0b0000000000001000000000000000000;
    int _20 = 0b0000000000010000000000000000000;
    int _21 = 0b0000000000100000000000000000000;
    int _22 = 0b0000000001000000000000000000000;
    int _23 = 0b0000000010000000000000000000000;
    int _24 = 0b0000000100000000000000000000000;
    int _25 = 0b0000001000000000000000000000000;
    int _26 = 0b0000010000000000000000000000000;
    int _27 = 0b0000100000000000000000000000000;
    int _28 = 0b0001000000000000000000000000000;
    int _29 = 0b0010000000000000000000000000000;
    int _30 = 0b0100000000000000000000000000000;
    int _31 = 0b1000000000000000000000000000000;
    int _32 = 0b1111111111111111111111111111111;
    int _XX = 0b10000000000000000000000000000000; // numeric overflow.
    int _33 = 0b10000000000000000000000000000001;
    int _34 = 0b11000000000000000000000000000000;
    int _35 = 0b11100000000000000000000000000000;
    int _36 = 0b11110000000000000000000000000000;
    int _37 = 0b11111000000000000000000000000000;
    int _38 = 0b11111100000000000000000000000000;
    int _39 = 0b11111110000000000000000000000000;
    int _40 = 0b11111111000000000000000000000000;
    int _41 = 0b11111111100000000000000000000000;
    int _42 = 0b11111111110000000000000000000000;
    int _43 = 0b11111111111000000000000000000000;
    int _44 = 0b11111111111100000000000000000000;
    int _45 = 0b11111111111110000000000000000000;
    int _46 = 0b11111111111111000000000000000000;
    int _47 = 0b11111111111111100000000000000000;
    int _48 = 0b11111111111111110000000000000000;
    int _49 = 0b11111111111111111000000000000000;
    int _50 = 0b11111111111111111100000000000000;
    int _51 = 0b11111111111111111110000000000000;
    int _52 = 0b11111111111111111111000000000000;
    int _53 = 0b11111111111111111111100000000000;
    int _54 = 0b11111111111111111111110000000000;
    int _55 = 0b11111111111111111111111000000000;
    int _56 = 0b11111111111111111111111100000000;
    int _57 = 0b11111111111111111111111110000000;
    int _58 = 0b11111111111111111111111111000000;
    int _59 = 0b11111111111111111111111111100000;
    int _60 = 0b11111111111111111111111111110000;
    int _61 = 0b11111111111111111111111111111000;
    int _62 = 0b11111111111111111111111111111100;
    int _63 = 0b11111111111111111111111111111110;
    int _64 = 0b11111111111111111111111111111111;

    System.out.println( " _0  = " + _0  );
    System.out.println( " _1  = " + _1  );
    System.out.println( " _2  = " + _2  );
    System.out.println( " _3  = " + _3  );
    System.out.println( " _4  = " + _4  );
    System.out.println( " _5  = " + _5  );
    System.out.println( " _6  = " + _6  );
    System.out.println( " _7  = " + _7  );
    System.out.println( " _8  = " + _8  );
    System.out.println( " _9  = " + _9  );
    System.out.println( " _10 = " + _10 );
    System.out.println( " _11 = " + _11 );
    System.out.println( " _12 = " + _12 );
    System.out.println( " _13 = " + _13 );
    System.out.println( " _14 = " + _14 );
    System.out.println( " _15 = " + _15 );
    System.out.println( " _16 = " + _16 );
    System.out.println( " _17 = " + _17 );
    System.out.println( " _18 = " + _18 );
    System.out.println( " _19 = " + _19 );
    System.out.println( " _20 = " + _20 );
    System.out.println( " _21 = " + _21 );
    System.out.println( " _22 = " + _22 );
    System.out.println( " _23 = " + _23 );
    System.out.println( " _24 = " + _24 );
    System.out.println( " _25 = " + _25 );
    System.out.println( " _26 = " + _26 );
    System.out.println( " _27 = " + _27 );
    System.out.println( " _28 = " + _28 );
    System.out.println( " _29 = " + _29 );
    System.out.println( " _30 = " + _30 );
    System.out.println( " _31 = " + _31 );
    System.out.println( " _32 = " + _32 );
    System.out.println( " _xx = " + _xx ); // -2147483648
    System.out.println( " _33 = " + _33 );
    System.out.println( " _34 = " + _34 );
    System.out.println( " _35 = " + _35 );
    System.out.println( " _36 = " + _36 );
    System.out.println( " _37 = " + _37 );
    System.out.println( " _38 = " + _38 );
    System.out.println( " _39 = " + _39 );
    System.out.println( " _40 = " + _40 );
    System.out.println( " _41 = " + _41 );
    System.out.println( " _42 = " + _42 );
    System.out.println( " _43 = " + _43 );
    System.out.println( " _44 = " + _44 );
    System.out.println( " _45 = " + _45 );
    System.out.println( " _46 = " + _46 );
    System.out.println( " _47 = " + _47 );
    System.out.println( " _48 = " + _48 );
    System.out.println( " _49 = " + _49 );
    System.out.println( " _50 = " + _50 );
    System.out.println( " _51 = " + _51 );
    System.out.println( " _52 = " + _52 );
    System.out.println( " _53 = " + _53 );
    System.out.println( " _54 = " + _54 );
    System.out.println( " _55 = " + _55 );
    System.out.println( " _56 = " + _56 );
    System.out.println( " _57 = " + _57 );
    System.out.println( " _58 = " + _58 );
    System.out.println( " _59 = " + _59 );
    System.out.println( " _60 = " + _60 );
    System.out.println( " _61 = " + _61 );
    System.out.println( " _62 = " + _62 );
    System.out.println( " _63 = " + _63 );
    System.out.println( " _64 = " + _64 );
Edward J Beckett
  • 5,061
  • 1
  • 41
  • 41
3

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.

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510

0

This is a workaround answer so you can still continue to basically infinite. I recommend a if(int > nearmax) then pass to new int Example:

int x = 2000000000;
x++;
int stacker = 0;
if (x > 2000000000)
{
int temp = x;
x = temp - 2000000000 
stacker++;
}

then you can unstack when necessary too...

say x = 0

x--;
if (x < 0 && stacker > 0)
{
int temp = x;
x = 2000000000 + temp;//plus because it's negative
stacker--;
}

this gives 2000000000 x 2000000000 and i mean...you could keep doing this so...ya...

of course you could go even further if you want to use negative numbers...

user2455808
  • 95
  • 1
  • 1
  • 9
0

I'm aware that this is a bit of a necropost, but I came across this and I thought I should share what I've done on my end to anyone who wants the "solved" or my attempt at a solve

package main;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Adder {
public static final int DIGITS = 25;

public static void main(String[] args) throws FileNotFoundException {
    Scanner input = new Scanner(new File("/Users/swapnil/IdeaProjects/Sum/src/Sum.txt"));
    analyze(input);
}

public static void analyze(Scanner input) {
    int lines = 0;
    while (input.hasNextLine()) {
        String line = input.nextLine();
        Scanner tokens = new Scanner(line);
        int[] operand = new int[DIGITS];
        initAdd(tokens, operand);
        while (tokens.hasNext()) {
            contAdd(tokens, operand);
        }
        System.out.print(" = ");
        printAsNumber(operand);
        System.out.println();
        lines++;
    }
    System.out.println();
    System.out.println("Total lines = " + lines);
}

public static int[] getNextOperand(Scanner tokens) {
    String number = tokens.next();
    int lastDigitIndex = DIGITS - number.length();
    int[] nextOp = new int[DIGITS];
    for (int i = lastDigitIndex; i < DIGITS; i++) {
        nextOp[i] = Character.getNumericValue(number.charAt(i - lastDigitIndex));
    }
    return nextOp;
}

public static void addColumns(Scanner tokens, int operand[], int nextOp[]) {
    for (int i = DIGITS - 1; i >= 0; i--) {
        operand[i] += nextOp[i];
        if (operand[i] > 9) {
            int currentDigit = operand[i] % 10;
            operand[i] = currentDigit;
            operand[i - 1]++;
        }
    }
}

public static void initAdd(Scanner tokens, int operand[]) {
    int[] nextOp = getNextOperand(tokens);
    printAsNumber(nextOp);
    addColumns(tokens, operand, nextOp);
}

public static void contAdd(Scanner tokens, int operand[]) {
    int[] nextOp = getNextOperand(tokens);
    System.out.print(" + ");
    printAsNumber(nextOp);
    addColumns(tokens, operand, nextOp);
}

public static void printAsNumber(int number[]) {
    int lastDigitIndex = DIGITS - 1;
    for (int i = 0; i < DIGITS; i++) {
        if (number[i] != 0) {
            lastDigitIndex = i;
            break;
        }
    }
    for (int i = lastDigitIndex; i < DIGITS; i++) {
        System.out.print(number[i]);
    }
}

}