我怎样才能检查在Java中乘以两个数字是否会导致溢出?

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

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; } 

你如何build议我最好的代码呢?

更新: ab在我的场景中总是非负的。

Java 8对于整数和长整数有Math.multiplyExactMath.addExact等。 这些在溢出时抛出未经检查的ArithmeticException

如果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 

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

你可以使用java.math.BigInteger来检查结果的大小(没有testing过代码):

 BigInteger bigC = BigInteger.valueOf(a) * multiply(BigInteger.valueOf(b)); if(bigC.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { c = Long.MAX_VALUE; } else { c = bigC.longValue() }