减去 2 个多头时的溢出检测
Overflow detection when subtracting 2 longs
我一直在研究 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;
}
因此,Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1
,特别是 Long.MIN_VALUE == -Long.MIN_VALUE
。所以如果a >= 0
、adding/subtracting、Long.MIN_VALUE
总会产生溢出。这意味着它是一种特殊情况,该方法必须测试 (A),并且仅在 a < 0
(B) 时才执行实际减法。由于我们已经测试了可能的溢出,我们可以简单地执行 (C)。
减去最小可能的数字 MIN_VALUE
与添加最大的数字 MAX_VALUE
相同。其实就是MAX_VALUE+1
和java一样,long
都是有符号的,0被编码成正数,所以正数比负数少一个。
这就是为什么 a
必须小于 0 才能使此减法(加法)起作用 (B)。但是,如果 a
小于 0 并且 b 是可能的最小数字。 a - b
总会成功的。 (C)
之所以检查这种特殊情况 (A),是因为这种情况下,最小可能数的绝对值比最大可能数大 1,因此 addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);
行会在 -b
位置失败
我一直在研究 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;
}
因此,Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1
,特别是 Long.MIN_VALUE == -Long.MIN_VALUE
。所以如果a >= 0
、adding/subtracting、Long.MIN_VALUE
总会产生溢出。这意味着它是一种特殊情况,该方法必须测试 (A),并且仅在 a < 0
(B) 时才执行实际减法。由于我们已经测试了可能的溢出,我们可以简单地执行 (C)。
减去最小可能的数字 MIN_VALUE
与添加最大的数字 MAX_VALUE
相同。其实就是MAX_VALUE+1
和java一样,long
都是有符号的,0被编码成正数,所以正数比负数少一个。
这就是为什么 a
必须小于 0 才能使此减法(加法)起作用 (B)。但是,如果 a
小于 0 并且 b 是可能的最小数字。 a - b
总会成功的。 (C)
之所以检查这种特殊情况 (A),是因为这种情况下,最小可能数的绝对值比最大可能数大 1,因此 addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);
行会在 -b