Reputation: 3598
I have been going through Apache's common math libs Link
In the below code snippet lines A, B, C doesn't make sense to me. Can someone shed some light on this ?
public static long subAndCheck(long a, long b) throws MathArithmeticException {
long ret;
if (b == Long.MIN_VALUE) { ----------A
if (a < 0) { --------------------B
ret = a - b; ----------------C
} else {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, -b);
}
} else {
// use additive inverse
ret = addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);
}
return ret;
}
private static long addAndCheck(long a, long b, Localizable pattern) throws MathArithmeticException {
final long result = a + b;
if (!((a ^ b) < 0 || (a ^ result) >= 0)) {
throw new MathArithmeticException(pattern, a, b);
}
return result;
}
Upvotes: 3
Views: 595
Reputation: 2284
Substracting the smallest possible number MIN_VALUE
is the same as adding the biggest number MAX_VALUE
. Actually it is even MAX_VALUE+1
as in java, long
's are all signed and 0 is encoded like positive numbers, so there is one less positive number than negative numbers.
That is why a
has to be smaller than 0 for this substraction (addition) to work (B). However, if a
is smaller than 0 and b is the smallest possible number. a - b
wil always succeed. (C)
The reason, why this special case is even checked (A), is because of the case, that the absolute of the smalles possible number is one bigger than the biggest possible number and thus the line addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);
would fail at the position -b
Upvotes: 1
Reputation: 459
So, Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1
, and specifically Long.MIN_VALUE == -Long.MIN_VALUE
. So if a >= 0
, adding/subtracting Long.MIN_VALUE
will always produce an overflow. This means it's a special case the method has to test for (A) and only carry out the actual subtraction if a < 0
(B). Since we already tested for a possible overflow we can simply do (C).
Upvotes: 3