Search code examples
javaprecisioninteger-overflow

Overflow detection when subtracting 2 longs


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;
    }

Solution

  • 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).