web-dev-qa-db-ja.com

ゼロによる除算のtry-catch

私の質問は、ゼロ除算の単純な例でのtry-catchブロックについてです。試行の最初の行が表示されますか?これらの2つの変数のいずれかをdoubleにキャストすると、プログラムはcatchブロックを認識しません。私の意見では、キャストするかどうかにかかわらず、catchブロックだけを実行する必要があります。このコードの何が問題になっていますか?

public static void main(String[] args) {

    int pay=8,payda=0;  

    try {

        double result=pay/(double)payda; // if I cast any of the two variables, program does not recognize the catch block, why is it so?
        System.out.println(result);
        System.out.println("inside-try");

    } catch (Exception e) {

        System.out.println("division by zero exception");
        System.out.println("inside-catch");

    }
}
14
Firat

ゼロ除算は浮動小数点数に有効です。

  • 1/0は無限大を生成します。
  • (-1)/ 0は-Infinityを生成します。
  • 0/0はNaNを生成します。

これらの「番号」は、IEEE754で適切に定義されています。

一方、ゼロによる整数除算は、無限大をintとして表すことができないためにスローされます。

23
kennytm

確認することをお勧めします:

if (divisor != 0) {
    // calculate
}

例外をキャッチするのではなく

14
Bozho

あなたは自称「初心者」なので、コードに関するより広範な問題を指摘するのは良い考えだと思います。 (私はそれが本番コードではないことを知っていますが、議論のためにそれがそうであったと仮定しましょう。)

  • 例外が予想される場合、例外を発生させる条件を検出すると、通常、より単純で、より明確で、より効率的になります。この場合、divisorがときどきゼロになると予想される場合は、除算を行う前にテストすることをお勧めします。

  • 一方、例外がまったく予期しないもの(つまり、「バグ」)である場合、最善の戦略は、例外を最も外側のレベルに伝播させることです。その時点で、アプリケーションキャッチはすべての例外をキャッチし、例外スタックトレースをログに記録して救済する必要があります。

  • 前の箇条書きとは別に、ExceptionRuntimeExceptionThrowable、またはErrorをキャッチすることはお勧めできません。これを行うと、おそらくキャッチするつもりのない多数の例外がキャッチされます。この場合、ArithmeticExceptionを期待しているので、それだけをキャッチする必要があります。

  • 金融アプリケーションでfloatまたはdoubleを使用することが正しいことはめったにありません。これらのタイプは正確ではありませんが、金融アプリケーションでは通常、正確に処理するために大量のお金が必要です。

  • より一般的には、浮動小数点数は一般の人々(および初心者)にとって本質的に理解するのが難しいです。人々が保持することを期待する多くの「真実」は実際には保持されません。たとえば、1.0/3.0 + 1.0/3.0 + 1.0/3.0の浮動小数点計算では、1.0は得られません。同様に(あなたが発見したように)ゼロによる除算は異なった振る舞いをします。浮動小数点を安全に使用したい場合は、落とし穴を理解する必要があります。

[〜#〜] edit [〜#〜] @ Jayのコメントに応えて最初のポイントを詳しく説明します。

最初に、私は意図的に「通常」という言葉を使用しました。予期された例外のスローを回避しても何も達成されない場合があります。

そうは言っても、一般的な「予期される」例外が発生することを望まないことがよくありますアプリケーションが状況にすぐに対処できない場合でも。たとえば、OPのコードがより大きなものの一部である場合、明示的にIllegalArgumentException(これがAPIコントラクトの違反である場合)をスローするか、チェックされたUserEnteredRubbishExceptionをスローする方がよい場合があります。これは悪いユーザー入力の結果です(そしてそれを報告/修正する機会があります)。

私たちが例外を「期待している」という事実は、定義による一般的なArithmeticExceptionが言うよりもそれについてもっと知っていることを意味します。一般的な例外の伝播を許可すると、catchブロックの多くのスタックフレームが適切に動作することが難しくなります。この場合、たとえば、リモートキャッチブロックはゼロ除算の原因を確実に診断できませんでした。 ArithmeticExceptionmightはアプリケーションの別の部分からのものであり、might notゼロ除算でさえあります!対処する方法は、より具体的な例外を明示的にスローすることです。

8
Stephen C

答えはプログラム自体の出力にあります-resultに対して「Infinity」を出力します。これは、Javaはゼロによる整数除算のみを許可しないためです。ゼロによる浮動小数点除算は有効であり、Infinityを生成します。

POSITIVE_INFINITYおよびNEGATIVE_INFINITY定数については、 Double および Float のドキュメントを参照してください。

3
danben

整数でゼロ除算するだけで、ArithmeticExceptionが発生します。 doubleまたはfloatでゼロで除算すると、Infinityになります。

2
Desintegr

2つのダブルを分割すると無限大が返されますが、スローされないためです。 isInfinite() を使用してこれを確認できます。ただし、適切な解決策(すでに述べたように)は、除算の前に分母を確認することです。

1

コードからRuntimeExceptionがスローされることを期待してはいけません。これらのExceptionsは簡単に回避できます(回避する必要があります)。

0
fastcodejava