如何检查Java中的两个数字是否会导致溢出?

问题描述 投票:93回答:14

我想处理两个数字相乘会导致溢出的特殊情况。代码看起来像这样:

int a = 20;
long b = 30;

// if a or b are big enough, this result will silently overflow
long c = a * b;

这是简化版本。在实际程序中,ab在运行时从其他位置获取。我想要实现的是这样的:

long c;
if (a * b will overflow) {
    c = Long.MAX_VALUE;
} else {
    c = a * b;
}

您如何建议我最好将此代码编写?

更新:在我的情况下,ab总是非负。

java overflow math long-integer
14个回答
82
投票

Java 8具有int和long的Math.multiplyExactMath.addExact等。它们在溢出时抛出未经检查的ArithmeticException


2
投票

我想以约翰·库格曼(John Kugelman)的答案为基础,而不用直接编辑来代替它。由于MIN_VALUE = -10的对称性,因此适用于他的测试用例(MAX_VALUE = 10MIN_VALUE == -MAX_VALUE),而二进制补码不是这种情况。实际上,MIN_VALUE == -MAX_VALUE - 1


2
投票

正如已经指出的那样,Java 8具有Math.xxxExact方法,这些方法会在溢出时引发异常。


1
投票

也许:


1
投票

也许这会帮助您:


-1
投票

c / c ++(long * long):


59
投票

如果ab均为正,则可以使用:

if (a != 0 && b > Long.MAX_VALUE / a) {
    // Overflow
}

如果您需要同时处理正数和负数,则更加复杂:

long maximum = Long.signum(a) == Long.signum(b) ? Long.MAX_VALUE : Long.MIN_VALUE;

if (a != 0 && (b > 0 && b > maximum / a ||
               b < 0 && b < maximum / a))
{
    // Overflow
}

这里有一张小桌子,我叫了起来检查一下,假装溢出发生在-10或+10:]

a =  5   b =  2     2 >  10 /  5
a =  2   b =  5     5 >  10 /  2
a = -5   b =  2     2 > -10 / -5
a = -2   b =  5     5 > -10 / -2
a =  5   b = -2    -2 < -10 /  5
a =  2   b = -5    -5 < -10 /  2
a = -5   b = -2    -2 <  10 / -5
a = -2   b = -5    -5 <  10 / -2

17
投票

有些Java库提供安全的算术运算,可以检查长时间的上溢/下溢。例如,Guava的LongMath.checkedMultiply(long a, long b)返回ab的乘积(前提是它没有溢出),如果ArithmeticException以有符号的a * b算术溢出,则抛出long


6
投票

您可以改用java.math.BigInteger并检查结果的大小(尚未测试代码):


6
投票

使用对数检查结果的大小。


4
投票

Java是否具有类似int.MaxValue的东西?如果是,请尝试


3
投票

从jruby偷走


3
投票

这是我想到的最简单的方法


2
投票

我不确定为什么没人在看这样的解决方案:

© www.soinside.com 2019 - 2024. All rights reserved.