Long + Long不大于Long.MAX_VALUE

时间:2012-01-29 22:16:43

标签: java long-integer

如果我有作业

Long c = a + b;

是否有一种简单的方法可以检查a + b是不是大于/小于Long.MAX_VALUE / Long.MIN_VALUE

4 个答案:

答案 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) < 0a有不同的标志,那么b就是如此,如果是这样,那么它永远不会溢出。或者,如果(a ^ (a + b)) >= 0,则a + ba具有相同的符号,因此它不会溢出并变为负数。

(有关这方面的更多技巧,请调查可爱的书籍Hacker's Delight。)

Apache根据ab的标志使用更复杂的案例。

答案 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