web-dev-qa-db-ja.com

32ビット整数の整数オーバーフローを検出するにはどうすればよいですか?

私はそのようなトピックが何度も尋ねられたことを知っていますが、私の質問は、intの完全な32ビットのオーバーフローについてです。例えば:

  11111111111111111111111111111111 +
  00000000000000000000000000000001 =
  00000000000000000000000000000000   //overflow!

私はこれについて同様の質問で topic を見つけましたが、アルゴリズムは完璧ではありません。

  11111111111111111111111111111111 +
  00000000000000000000000000000000 =
  00000000000000000000000000000000  //overflow!

これをチェックするための簡単で迅速、安全な方法はありますか?

29
ashur

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);
}
34
Patryk Czarnik
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
   // Overflow!
13
Tim B

この方法を試してください:

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

8
Vusal

オーバーフローは、2つのオペランドの最上位ビットの論理式と(切り捨てられた)結果によって検出できます(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;
}
3
Durandal

私が考えることができる最も直感的な方法:合計(または差)をlongとして計算し、その合計をintに変換して、値が変更されたかどうかを確認します。

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

最新の64ビットプロセッサでは、longsを使用することはintsを使用することと同じくらい効率的であることに注意してください(逆も同様です)。したがって、オーバーフローをチェックするか、longsを使用するかを選択できる場合は、後者を使用します。

1
GOTO 0