47

I know such topic was asked several times, but my question is about overflow on full 32 bits of int. For example:

  11111111111111111111111111111111 +
  00000000000000000000000000000001 =
  00000000000000000000000000000000   //overflow!

I found topic with similar question about this, however the algorithm is not perfect.

  11111111111111111111111111111111 +
  00000000000000000000000000000000 =
  00000000000000000000000000000000  //overflow!

Is there any simple, fast, safer way to check this ?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
ashur
  • 4,177
  • 14
  • 53
  • 85
  • 2
    https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow – Ben Dale Jan 20 '14 at 12:07
  • BTW, Java int is always 32 bits (regardless of the architecture that your given JVM is running on [https://stackoverflow.com/questions/18017752/will-an-int-be-32bit-and-a-long-64bit-regardless-of-whether-the-system-is-32-or]): "By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1" (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html). So the 32-bit specification here seems to be a bit irrelevant/moot. – cellepo Nov 11 '18 at 20:13

5 Answers5

75

Math.addExact throws exception on overflow

Since Java 8 there is a set of methods in the Math class:

…and versions for long as well.

Each of these methods throws ArithmeticException if overflow happens. Otherwise they return the proper result if it fits within the range.

Example of addition:

int x = 2_000_000_000;
int y = 1_000_000_000;
try {
    int result = Math.addExact(x, y);
    System.out.println("The proper result is " + result);
} catch(ArithmeticException e) {
    System.out.println("Sorry, " + e);
}

See this code run live at IdeOne.com.

Sorry, java.lang.ArithmeticException: integer overflow

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Patryk Czarnik
  • 866
  • 7
  • 5
25
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
   // Overflow!
Tim B
  • 40,716
  • 16
  • 83
  • 128
  • Are x & y assumed to be long's themselves? If they were instead int's, I don't think this would work (since the overflow would go undetected before the long cast); am I correct? – cellepo Nov 11 '18 at 20:19
  • 9
    You are not correct. X gets cast to long before addition (precedence). long+int the int gets converted to long and you end up with long+long. Therefore the entire operation is done at 64 bit precision. – Tim B Nov 11 '18 at 22:55
  • 1
    Ah ok so the cast has precedence over the addition operator. Thanks! – cellepo Nov 12 '18 at 02:12
15

Try this way:

boolean isOverflow(int left, int right) {
    return right > 0
            ? Integer.MAX_VALUE - right < left
            : Integer.MIN_VALUE - right > left;
}

From: https://wiki.sei.cmu.edu/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow

Vüsal
  • 2,580
  • 1
  • 12
  • 31
3

Overflow can be detected by a logical expression of the most significant bit of the two operands and the (truncated) result (I took the logical expression from the MC68030 manual):

/**
 * Add two int's with overflow detection (r = s + d)
 */
public static int add(int s, int d) throws ArithmeticException {
    int r = s + d;
    if (((s & d & ~r) | (~s & ~d & r)) < 0)
        throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");
    return r;
}
Durandal
  • 19,919
  • 4
  • 36
  • 70
3

The most intuitive method I can think of: calculate the sum (or difference) as a long, then convert that sum to an int and see if its value has changed.

long longSum = (long) a + b;
int sum = (int) longSum;
if (sum == longSum) {
    // sum contains the correct result
} else {
    // overflow/underflow
}

Remember that on modern 64 bit processors, working with longs is no less efficient than working with ints (the opposite may be true). So if you have a choice between checking for overflows or using longs, go for the latter.

GOTO 0
  • 42,323
  • 22
  • 125
  • 158