我想处理两个数字相乘会导致溢出的特殊情况。代码看起来像这样:
int a = 20;
long b = 30;
// if a or b are big enough, this result will silently overflow
long c = a * b;
这是简化版本。在实际程序中,a
和b
在运行时从其他位置获取。我想要实现的是这样的:
long c;
if (a * b will overflow) {
c = Long.MAX_VALUE;
} else {
c = a * b;
}
您如何建议我最好将此代码编写?
更新:在我的情况下,a
和b
总是非负。
Java 8具有int和long的Math.multiplyExact
,Math.addExact
等。它们在溢出时抛出未经检查的ArithmeticException
。
我想以约翰·库格曼(John Kugelman)的答案为基础,而不用直接编辑来代替它。由于MIN_VALUE = -10
的对称性,因此适用于他的测试用例(MAX_VALUE = 10
,MIN_VALUE == -MAX_VALUE
),而二进制补码不是这种情况。实际上,MIN_VALUE == -MAX_VALUE - 1
。
正如已经指出的那样,Java 8具有Math.xxxExact方法,这些方法会在溢出时引发异常。
也许:
也许这会帮助您:
c / c ++(long * long):
如果a
和b
均为正,则可以使用:
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
有些Java库提供安全的算术运算,可以检查长时间的上溢/下溢。例如,Guava的LongMath.checkedMultiply(long a, long b)返回a
和b
的乘积(前提是它没有溢出),如果ArithmeticException
以有符号的a * b
算术溢出,则抛出long
。
您可以改用java.math.BigInteger并检查结果的大小(尚未测试代码):
使用对数检查结果的大小。
Java是否具有类似int.MaxValue的东西?如果是,请尝试
从jruby偷走
这是我想到的最简单的方法
我不确定为什么没人在看这样的解决方案: