我知道这样的主题是多次问的,但是我的问题是关于在完整32个int 上溢出。例如:
11111111111111111111111111111111 +
00000000000000000000000000000001 =
00000000000000000000000000000000 //overflow!
我发现了对此有类似问题的主题,但是算法并不完美。
11111111111111111111111111111111 +
00000000000000000000000000000000 =
00000000000000000000000000000000 //overflow!
是否有任何简单,快速,更安全的方法来检查此问题?
Math.addExact
在溢出
上引发异常自Java 8以来,Math
类中有一组方法:
-
toIntExact(long)
-
addExact(int,int)
-
subtractExact(int,int)
-
multiplyExact(int,int)
…还有长期的版本。
如果发生溢出,则每种方法都会抛出ArithmeticException
。否则,如果适合范围内,他们会返回适当的结果。
加法的示例:
int x = 2_000_000_000;
int y = 1_000_000_000;
try {
int result = Math.addExact(x, y);
System.out.println("The proper result is " + result);
} catch(ArithmeticException e) {
System.out.println("Sorry, " + e);
}
请参阅此代码在IDEONE.com上进行直播。
对不起,java.lang.arithmeticexception:整数溢出
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
// Overflow!
尝试以这种方式:
boolean isOverflow(int left, int right) {
return right > 0
? Integer.MAX_VALUE - right < left
: Integer.MIN_VALUE - right > left;
}
来自:https://wiki.sei.cmu.edu/confluence/display/java/java/num00-j. detect or prevent prevent integer integer integer voverflow
溢出可以通过两个操作数中最重要的位和(截断)结果的逻辑表达来检测到(我从MC68030手册中获取逻辑表达式):
/**
* Add two int's with overflow detection (r = s + d)
*/
public static int add(int s, int d) throws ArithmeticException {
int r = s + d;
if (((s & d & ~r) | (~s & ~d & r)) < 0)
throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");
return r;
}
我能想到的最直观的方法:将总和(或差异)计算为 long
,然后将该总和转换为 int
,看看其值是否已更改。
long longSum = (long) a + b;
int sum = (int) longSum;
if (sum == longSum) {
// sum contains the correct result
} else {
// overflow/underflow
}
请记住,在现代64位处理器上,使用long
S的效率与使用int
S相比(相反的可能是正确的)。因此,如果您可以在检查溢出或使用long
s之间进行选择,请选择后者。