减去2个long时的溢出检测

时间:2017-02-20 11:10:55

标签: java precision integer-overflow

我一直在浏览Apache的常用数学库Link

在下面的代码片段中,A,B,C对我没有意义。有人可以对此有所了解吗?

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

2 个答案:

答案 0 :(得分:3)

所以,vmlinux,特别是Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1。因此,如果Long.MIN_VALUE == -Long.MIN_VALUE,添加/减去a >= 0将始终产生溢出。这意味着该方法必须测试(A)并且仅在Long.MIN_VALUE(B)时执行实际减法的特殊情况。由于我们已经测试了可能的溢出,我们可以简单地做(C)。

答案 1 :(得分:1)

减去最小可能的数字MIN_VALUE与添加最大数字MAX_VALUE相同。实际上它甚至是MAX_VALUE+1,因为在java中,long都被签名,0被编码为正数,因此正数少于负数。

这就是为什么a必须小于0才能使这个减法(加法)工作(B)。但是,如果a小于0且b是可能的最小数字。 a - b总是会成功的。 (C)

为什么甚至检查这种特殊情况(A)的原因是,因为这种情况,尽可能小的绝对值比最大可能的数字大一个,因此行addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);会失败在-b

位置