我一直在浏览 Apache 的常用数学库链接
在下面的代码片段行中,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;
}
所以,Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1
,特别是Long.MIN_VALUE == -Long.MIN_VALUE
。因此,如果a >= 0
,加/减Long.MIN_VALUE
总是会产生溢出。这意味着这是一个特殊情况,该方法必须测试(A),并且只有在a < 0
(B)时才执行实际减法。由于我们已经测试了可能的溢出,我们可以简单地做(C)。
MIN_VALUE
减去尽可能小的数字与MAX_VALUE
添加最大数字相同。实际上它甚至像在java中一样MAX_VALUE+1
,long
都是有符号的,0像正数一样编码,所以正数比负数少一个。
这就是为什么a
必须小于 0 才能使此减法(加法)起作用 (B)。但是,如果a
小于 0 并且 b 是可能的最小数字。a - b
总是成功的。(三)
之所以甚至检查这种特殊情况(A),是因为这种情况,小可能数的绝对值比最大可能数大一,因此addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);
线将在位置-b