46

我知道这样的话题被问了好几次,但我的问题是关于满 32 位 int 的溢出。例如:

  11111111111111111111111111111111 +
  00000000000000000000000000000001 =
  00000000000000000000000000000000   //overflow!

我找到了与此相关的类似问题的主题,但是算法并不完美。

  11111111111111111111111111111111 +
  00000000000000000000000000000000 =
  00000000000000000000000000000000  //overflow!

有没有简单、快速、安全的方法来检查这个?

4

5 回答 5

72

Math.addExact溢出时抛出异常

从 Java 8 开始,该类中有一组方法Math

……以及长期的版本。

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:整数溢出

于 2018-02-07T07:15:26.217 回答
23
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
   // Overflow!
于 2014-01-20T12:08:00.710 回答
14

试试这个方法:

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/NUM00-J.+Detect+or+prevent+integer+overflow

于 2018-05-17T09:08:36.873 回答
3

溢出可以通过两个操作数的最高有效位的逻辑表达式和(截断的)结果来检测(我从 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;
}
于 2014-01-20T15:38:13.813 回答
2

我能想到的最直观的方法:将总和(或差)计算为 a long,然后将该总和转换为 anint并查看其值是否发生了变化。

long longSum = (long) a + b;
int sum = (int) longSum;
if (sum == longSum) {
    // sum contains the correct result
} else {
    // overflow/underflow
}

请记住,在现代 64 位处理器上,使用longs 的效率不亚于使用ints(可能相反)。因此,如果您可以在检查溢出或使用longs 之间进行选择,请选择后者。

于 2018-04-05T20:51:03.103 回答