如何检查在 Java 中将两个数字相乘是否会导致溢出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1657834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I check if multiplying two numbers in Java will cause an overflow?
提问by Steve McLeod
I want to handle the special case where multiplying two numbers together causes an overflow. The code looks something like this:
我想处理将两个数字相乘导致溢出的特殊情况。代码如下所示:
int a = 20;
long b = 30;
// if a or b are big enough, this result will silently overflow
long c = a * b;
That's a simplified version. In the real program a
and b
are sourced elsewhere at runtime. What I want to achieve is something like this:
那是简化版。在实际程序中,a
并b
在运行时从别处获取。我想要实现的是这样的:
long c;
if (a * b will overflow) {
c = Long.MAX_VALUE;
} else {
c = a * b;
}
How do you suggest I best code this?
你如何建议我最好地编码这个?
Update: a
and b
are always non-negative in my scenario.
更新:a
并且b
在我的场景中总是非负的。
采纳答案by bcoughlan
Java 8 has Math.multiplyExact
, Math.addExact
etc. for ints and long. These throw an unchecked ArithmeticException
on overflow.
Java的8有Math.multiplyExact
,Math.addExact
等,为整数且长。这些会引发未经检查ArithmeticException
的溢出。
回答by Thomas Jung
Maybe:
也许:
if(b!= 0 && a * b / b != a) //overflow
Not sure about this "solution".
不确定这个“解决方案”。
Edit: Added b != 0.
编辑:添加 b != 0。
Before you downvote: a * b / b won't be optimized. This would be compiler bug. I do still not see a case where the overflow bug can be masked.
在你downvote 之前: a * b / b 不会被优化。这将是编译器错误。我仍然没有看到可以掩盖溢出错误的情况。
回答by Ulf Lindback
You could use java.math.BigInteger instead and check the size of the result (haven't tested the code):
您可以改用 java.math.BigInteger 并检查结果的大小(尚未测试代码):
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()
}
回答by High Performance Mark
Use logarithms to check the size of the result.
使用对数来检查结果的大小。
回答by nothrow
Does Java has something like int.MaxValue? If yes, then try
Java 有类似 int.MaxValue 的东西吗?如果是,那么尝试
if (b != 0 && Math.abs(a) > Math.abs(Long.MAX_VALUE / b))
{
// it will overflow
}
edit: seen Long.MAX_VALUE in question
编辑:看到 Long.MAX_VALUE 有问题
回答by John Kugelman
If a
and b
are both positive then you can use:
如果a
和b
都是正数,那么您可以使用:
if (a != 0 && b > Long.MAX_VALUE / a) {
// Overflow
}
If you need to deal with both positive and negative numbers then it's more complicated:
如果您需要同时处理正数和负数,那就更复杂了:
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
}
Here's a little table I whipped up to check this, pretending that overflow happens at -10 or +10:
这是我为了检查这一点而制作的一张小桌子,假装溢出发生在 -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
回答by fastcodejava
I am not sure why nobody is looking at solution like:
我不知道为什么没有人在寻找解决方案,例如:
if (Long.MAX_VALUE/a > b) {
// overflows
}
Choose a to be larger of the two numbers.
选择两个数字中较大的一个。
回答by dfa
maybe this will help you:
也许这会帮助你:
/**
* @throws ArithmeticException on integer overflow
*/
static long multiply(long a, long b) {
double c = (double) a * b;
long d = a * b;
if ((long) c != d) {
throw new ArithmeticException("int overflow");
} else {
return d;
}
}
回答by rogerdpack
Stolen from jruby
从 jruby 窃取
long result = a * b;
if (a != 0 && result / a != b) {
// overflow
}
UPDATE: This code is short and works well; however, it fails for a = -1, b = Long.MIN_VALUE.
更新:这段代码很短而且运行良好;但是,它在 a = -1, b = Long.MIN_VALUE 时失败。
One possible enhancement:
一种可能的增强:
long result = a * b;
if( (Math.signum(a) * Math.signum(b) != Math.signum(result)) ||
(a != 0L && result / a != b)) {
// overflow
}
Note that this will catch some overflows without any division.
请注意,这会在没有任何除法的情况下捕获一些溢出。
回答by xuan
c / c ++ (long * long):
c / c ++(长*长):
const int64_ w = (int64_) a * (int64_) b;
if ((long) (w >> sizeof(long) * 8) != (long) w >> (sizeof(long) * 8 - 1))
// overflow
java (int * int, sorry I didn't find int64 in java):
java(int * int,抱歉我没有在java中找到int64):
const long w = (long) a * (long) b;
int bits = 32; // int is 32bits in java
if ( (int) (w >> bits) != (int) (w >> (bits - 1))) {
// overflow
}
1.save the result in large type (int*int put the result to long, long*long put to int64)
1.将结果保存为大类型(int*int 将结果放入long,long*long 放入int64)
2.cmp result >> bits and result >> (bits - 1)
2.cmp 结果 >> 位和结果 >> (位 - 1)
回答by reprogrammer
There are Java libraries that provide safe arithmetic operations, which check long overflow/underflow. For example, Guava's LongMath.checkedMultiply(long a, long b)returns the product of a
and b
, provided it does not overflow, and throws ArithmeticException
if a * b
overflows in signed long
arithmetic.
有提供安全算术运算的 Java 库,用于检查长溢出/下溢。例如,番石榴的LongMath.checkedMultiply(长,长二)返回的产品a
和b
,只要它不溢出,并抛出ArithmeticException
如果a * b
溢出登录long
算术。