9

実際に適用する前に、算術演算がデータ型の上限を超えるかどうかをどのように確認できますか。

Short.MAX_VALUEJavaでの略して上限は32767であり、328 * 100を乗算していますが、乗算後の回答はすでにオーバーフローしており、回答は-32736であり、これは確かに小さいため、実際には比較できません。Short.MAX_VALUE

別の例を見てみましょう。私はintforループで17^10(17の10乗)を計算する価値があります。どの段階で答えが溢れたかをどうやって知ることができますか。

これShortint物事は単なる例です。この問題を、すべてのデータ型に対して正確に何ができるかをより大きな認識で考えてください。

グーグルを試しましたが、概念を理解するのに役立つ良いリンクが見つかりませんでした。

4

3 に答える 3

5

オーバーフローチェックには、次の3つの方法があります。

より大きな型とダウンキャストを使用する:入力を次に大きなプリミティブ整数型にキャストし、より大きなサイズで演算を実行します。元の小さいタイプのオーバーフローがないか、各中間結果を確認します。範囲チェックが失敗した場合、ArithmeticExceptionをスローします。

入力の事前チェック:各算術演算子への入力をチェックして、オーバーフローが発生しないことを確認します。操作が実行された場合に操作がオーバーフローする場合は、ArithmeticExceptionを再度スローします。それ以外の場合は、操作を実行します。

例えば:

static void preAddCheck(int left, int right) throws ArithmeticException {
   if (right > 0 ? left > Integer.MAX_VALUE - right : left < Integer.MIN_VALUE - right) {
    throw new ArithmeticException("Integer overflow");
  }
}

BigInteger:入力をBigInteger型のオブジェクトに変換し、BigIntegerメソッドを使用してすべての演算を実行します。オーバーフロー時にArithmeticExceptionがスローされます。

于 2012-08-04T11:22:40.183 に答える
4

このようなメソッドをJava8のMathパッケージに含める計画がありますが、現在の状況はわかりません。いくつかのソースコードはここから入手できます。実装がどのようにテストされているかはわかりませんが、それでアイデアが得られる可能性があります。

たとえば、int乗算は、longを使用して実行されます。

public static int multiplyExact(int x, int y) {
    long r = (long)x * (long)y;
    if ((int)r != r) {
        throw new ArithmeticException("long overflow");
    }
    return (int)r;
}

ただし、長い乗算では、より複雑なアルゴリズムが使用されます。

public static long multiplyExact(long x, long y) {
    long r = x * y;
    long ax = Math.abs(x);
    long ay = Math.abs(y);
    if (((ax | ay) >>> 31 != 0)) {
        // Some bits greater than 2^31 that might cause overflow
        // Check the result using the divide operator
        // and check for the special case of Long.MIN_VALUE * -1
       if (((y != 0) && (r / y != x)) ||
            (x == Long.MIN_VALUE && y == -1)) {
            throw new ArithmeticException("long overflow");
        }
    }
    return r;
}  
于 2012-08-04T11:25:25.653 に答える
2

可能な限り最大のタイプであるBigInteger/BigDecimalを使用して計算を行います。次に、その大きさに応じて適切なタイプに値を割り当てます...興味深いことに、これにはいくつかの便利なメソッドがあります...値をshortに含めることができない場合、shortValueExtractはArithmetricExceptionをスローします。

BigDecimal result = BigDecimal.valueOf(328).multiply(
        BigDecimal.valueOf(100));
try {
    short shortResult = result.shortValueExact();
} catch (ArithmeticException e) {
    // overflow
    System.out.println("Overflow!");
}

try {
    int intResult = result.intValueExact();
} catch (ArithmeticException e) {
    // overflow
}
于 2012-08-04T11:36:50.483 に答える