问题
我想处理两个数字相乘导致溢出的特殊情况。代码看起来像这样:
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在我的方案中始终是非负的。
#1 热门回答(74 赞)
Java 8 hasMath.multiplyExact,Math.addExactetc。对于整数和长期。这些抛出一个未经检查的ArithmeticException溢出。
#2 热门回答(55 赞)
如果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
#3 热门回答(17 赞)
有些Java库提供安全的算术运算,可检查长溢出/下溢。例如,Guava'sLongMath.checkedMultiply(long a, long b)返回a和b的产品,前提是它没有溢出,并且在signedlong算术中抛出ArithmeticExceptionifa * boverflows。