私はそのようなトピックが何度も尋ねられたことを知っていますが、私の質問は、intの完全な32ビットのオーバーフローについてです。例えば:
11111111111111111111111111111111 +
00000000000000000000000000000001 =
00000000000000000000000000000000 //overflow!
私はこれについて同様の質問で topic を見つけましたが、アルゴリズムは完璧ではありません。
11111111111111111111111111111111 +
00000000000000000000000000000000 =
00000000000000000000000000000000 //overflow!
これをチェックするための簡単で迅速、安全な方法はありますか?
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);
}
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/NUM00-J.+Detect+or+prevent+integer+overflow
オーバーフローは、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;
}
私が考えることができる最も直感的な方法:合計(または差)を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を使用するかを選択できる場合は、後者を使用します。