如果我有作业
Long c = a + b;
是否有一种简单的方法可以检查a + b
是不是大于/小于Long.MAX_VALUE
/ Long.MIN_VALUE
?
答案 0 :(得分:17)
使用Guava,就像
一样简单long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow
这是我想的,确实很可读。 (LongMath Javadoc here。)
为了公平起见,我会提到Apache Commons提供ArithmeticUtils.addAndCheck(long, long)
。
如果你想知道它们是如何工作的,那么答案就是Guava的一点点hackery:如果(a ^ b) < 0 | (a ^ (a + b)) >= 0
,结果不会溢出。这是基于两个数字的按位异或是非负的技巧,如果它们具有相同的符号。
如果(a ^ b) < 0
和a
有不同的标志,那么b
就是如此,如果是这样,那么它永远不会溢出。或者,如果(a ^ (a + b)) >= 0
,则a + b
与a
具有相同的符号,因此它不会溢出并变为负数。
(有关这方面的更多技巧,请调查可爱的书籍Hacker's Delight。)
Apache根据a
和b
的标志使用更复杂的案例。
答案 1 :(得分:13)
如果它们具有相同的符号(并且都是!0
),那么这只是一个问题,因为否则您将不会溢出。如果发生溢出,结果的符号将会翻转。所以:
long r = a + b;
if ( (a < 0 && b < 0 && r >= 0) ||
(a > 0 && b > 0 && r <= 0) ) {
// Overflow occurred
}
答案 2 :(得分:0)
一种选择是使用BigInteger
类进行精确计算,然后检查结果是否大于或小于有问题的值。例如:
if (BigInteger.valueOf(a).add(BigInteger.valueOf(b)).compareTo(BigInteger.valueOf(Long.MAX_VALUE) > 1) {
/* Overflow occurred. */
} else {
/* No overflow occurred.
}
希望这有帮助!
答案 3 :(得分:0)
简单的路线:
if(a/2+b/2+(a&b&1)>long.MAX_VALUE/2||a/2+b/2<long.MIN_VALUE/2)...
你只需要希望它不会优化到(a+b)/2