Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java number exceeds long.max_value - how to detect?

Tags:

java

numbers

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.

like image 354
jurchiks Avatar asked Sep 10 '12 08:09

jurchiks


2 Answers

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.

like image 105
Peter Lawrey Avatar answered Oct 04 '22 01:10

Peter Lawrey


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

like image 26
Daniel André Avatar answered Oct 04 '22 01:10

Daniel André