jurchiks
jurchiks

Reputation: 1433

java number exceeds long.max_value - how to detect?

I'm having problems detecting if a sum/multiplication of two numbers exceeds the maximum value of a long integer.
Example code:

long a = 2 * Long.MAX_VALUE;
System.out.println("long.max * smth > long.max... or is it? a=" + a);

This gives me -2, while I would expect it to throw a NumberFormatException...

Is there a simple way of making this work? Because I have some code that does multiplications in nested IF blocks or additions in a loop and I would hate to add more IFs to each IF or inside the loop.

Edit: oh well, it seems that this answer from another question is the most appropriate for what I need: https://stackoverflow.com/a/9057367/540394
I don't want to do boxing/unboxing as it adds unnecassary overhead, and this way is very short, which is a huge plus to me. I'll just write two short functions to do these checks and return the min or max long.

Edit2: here's the function for limiting a long to its min/max value according to the answer I linked to above:

/**
 * @param a : one of the two numbers added/multiplied
 * @param b : the other of the two numbers
 * @param c : the result of the addition/multiplication
 * @return the minimum or maximum value of a long integer if addition/multiplication of a and b is less than Long.MIN_VALUE or more than Long.MAX_VALUE
 */
public static long limitLong(long a, long b, long c)
{
    return (((a > 0) && (b > 0) && (c <= 0))
        ? Long.MAX_VALUE
        : (((a < 0) && (b < 0) && (c >= 0)) ? Long.MIN_VALUE : c));
}

Tell me if you think this is wrong.

Upvotes: 8

Views: 24979

Answers (3)

Daniel Andr&#233;
Daniel Andr&#233;

Reputation: 1258

Exceding the maximum value of a long doesnt throw an exception, instead it cicles back. If you do this:

Long.MAX_VALUE + 1

you will notice that the result is the equivalent to Long.MIN_VALUE

If you want it to throw an exception check if it reached the max value and throw the exception

[Edit]

You can also use the Guava Library to check if there is an overflow when you sum two longs;

long c = LongMath.checkedAdd(a, b);

this throws an exception when an overflow occurs.

You can find the javadoc here

Upvotes: 5

Peter Lawrey
Peter Lawrey

Reputation: 533880

If you can't be sure the result will be less than 9 trillion trillion, I would use double or BigInteger Getting an error doesn't help you very much because you still need to know what to do about.

Much better that you don't get an error in the first place by validating your input to ensure they are in range and if the range of the result is larger than long use a type which can handle this.

With BigInteger you can do

BigInteger a = BigInteger.valueOf(2).multiply(BigInteger.valueOf(Long.MAX_VALUE));
long l = a.longValue();
if (a.compareTo(BigInteger.valueOf(l)) == 0) {
    // ok
} else {
    // error
}

With double you can do

double d = 2.0 * Long.MAX_VALUE;
long l = (long) Math.max(Long.MIN_VALUE, Math.min(Long.MAX_VALUE, d));
// or as a helper method.
long l = boundedCast(d);

Note: using double instead of long can result in some loss of precision.

I would prefer to avoid the need for an error block in the first place.

Upvotes: 5

Bharat Sinha
Bharat Sinha

Reputation: 14373

Long values exceeding MAX_VALUE doesn't throw any exception. You need to check and handle such situations manually.

ALthough as @PeterLawrey suggested you should consider using double and BigInteger.

Upvotes: 0

Related Questions