如何在32位int上检测整数溢出?

时间:2014-01-20 12:02:24

标签: java integer bit-manipulation integer-overflow integer-arithmetic

我知道这样的主题被多次询问,但我的问题是关于整个32位int 的溢出。例如:

  11111111111111111111111111111111 +
  00000000000000000000000000000001 =
  00000000000000000000000000000000   //overflow!

我发现topic有类似的问题,但算法并不完美。

  11111111111111111111111111111111 +
  00000000000000000000000000000000 =
  00000000000000000000000000000000  //overflow!

有没有简单快捷的方法来检查这个?

5 个答案:

答案 0 :(得分:27)

从Java 8开始,Math类中有一组方法: toIntExact (long), addExact (int,int), subtractExact (int,int), multiplyExact (int ,int)和版本也很长。 如果发生溢出,它们会抛出ArithmeticException,如果它符合范围,它们将返回正确的结果。

添加示例:

int x = 2000000000;
int y = 1000000000;
try {
    int result = Math.addExact(x, y);
    System.out.println("The proper result is " + result);
} catch(ArithmeticException e) {
    System.out.println("Sorry, " + e);
}

答案 1 :(得分:12)

long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
   // Overflow!

答案 2 :(得分:6)

尝试这种方式:

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

答案 3 :(得分:2)

我能想到的最直观的方法:将总和(或差异)计算为long,然后将该总和转换为int并查看其值是否已更改。

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

请记住,在现代64位处理器上,使用long的效率并不比使用int s更有效(反之亦然)。因此,如果您可以选择检查溢出或使用long,请选择后者。

答案 4 :(得分:1)

可以通过两个操作数的最高位和(截断的)结果的逻辑表达式检测溢出(我从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;
}