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



我知道这样的主题是多次问的,但是我的问题是关于在完整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之间进行选择,请选择后者。

最新更新