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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With