views:

220

answers:

5

How does Java handle integer underflows and overflows?

Leading on from that, how would you check/test that this is occurring?

+1  A: 

Seems relevant here: Other Question..

phatmanace
A: 

It doesn't do anything -- the under/overflow just happens.

A "-1" that is the result of a computation that overflowed is no different from the "-1" that resulted from any other information. So you can't tell via some status or by inspecting just a value whether it's overflowed.

But you can be smart about your computations in order to avoid overflow, if it matters, or at least know when it will happen. What's your situation?

Sean Owen
It's not really a situation, just something that I'm curious about and got me thinking. If you need an example use-case, here's one: I have a class with it's own internal variable called 'seconds'. I have two methods which take an integer as a parameter and will increment or decrement (respectively) 'seconds' by that much. How would you unit test that an underflow/overflow is occurring and how would you prevent it from occurring?
KushalP
+4  A: 

If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there.

You can check that beforehand using the greater than or lesser than operators.

if (someInt + valueToAdd < someInt) {
    // Overflowed!
}

if (someInt - valueToSubstract > someInt) {
    // Underflowed!
}

If you think that this may occur more than often, then consider using a datatype or object which can store larger values, e.g. long or maybe java.math.BigInteger. The last one doesn't overflow, practically, the available JVM memory is the limit.

BalusC
Actually this wouldn't work as intended, consider: someInt = 2; valueToAdd = -1; if (someInt + valueToAdd < someInt) { // Oops it wasnt overflow, but we treat it as if... }
Durandal
Then add an extra check whether the value to add/substract is negative/positive so that you can determine if it should be added or substracted ;)
BalusC
@BalusC - the point is that detecting `int` overflow / underflow is not quite as simple as your answer is saying.
Stephen C
I'd expect that the variablenames already covered that ;) Regardless, thank you for the nitpick.
BalusC
A: 

It wraps around.

e.g:

public class test {

public static void main(String[] args) {
    int i = Integer.MAX_VALUE;
    int j = Integer.MIN_VALUE;

    System.out.println(i+1);
    System.out.println(j-1);

}

}

prints

-2147483648

2147483647

Peter Tillemans
+1  A: 

Well, as far as primitive integer types go, Java doesnt handle Over/Underflow at all (for float and double the behaviour is different, it will flush to +/- infinity just as IEEE-754 mandates).

When adding two int's, you will get no indication when an overflow occurs. A simple method to check for overflow is to use the next bigger type to actually perform the operation and check if the result is still in range for the source type:

public int addWithOverflowCheck(int a, int b) {
    // the cast of a is required, to make the + work with long precision,
    // if we just added (a + b) the addition would use int precision and
    // the result would be cast to long afterwards!
    long result = ((long) a) + b;
    if (result > Integer.MAX_VALUE) {
         throw new RuntimeException("Overflow occured");
    } else if (result < Integer.MIN_VALUE) {
         throw new RuntimeException("Underflow occured");
    }
    // at this point we can safely cast back to int, we checked before
    // that the value will be withing int's limits
    return (int) result;
}

What you would do in place of the throw clauses, depends on your applications requirements (throw, flush to min/max or just log whatever). If you want to detect overflow on long operations, you're out of luck with primitives, use BigInteger instead.

Durandal
@Durandal - now generalize that to `long` :-)
Stephen C