66

java.lang.ArithmeticException: / by zero次のステートメントは、明らかなようにスローします。

System.out.println(0/0);

リテラル0はリテラルと見なされint、ゼロ除算は整数演算では許可されないためです。

ただし、次のケースでは、のような例外はスローされませんjava.lang.ArithmeticException: / by zero

int a = 0;
double b = 6.199;
System.out.println((b/a));

と表示されますInfinity

次のステートメントはNaN、例外なく (Not a Number) を生成します。

System.out.println(0D/0); //or 0.0/0, or 0.0/0.0 or 0/0.0 - floating point arithmetic.

この場合、両方のオペランドが double と見なされます。


同様に、次のステートメントは例外をスローしません。

double div1 = 0D/0; //or 0D/0D
double div2 = 0/0D; //or 0D/0D

System.out.printf("div1 = %s : div2 = %s%n", div1, div2);
System.out.printf("div1 == div2 : %b%n", div1 == div2);
System.out.printf("div1 == div1 : %b%n", div1 == div1);
System.out.printf("div2 == div2 : %b%n", div2 == div2);
System.out.printf("Double.NaN == Double.NaN : %b%n", Double.NaN == Double.NaN);
System.out.printf("Float.NaN == Float.NaN : %b%n", Float.NaN == Float.NaN);

次の出力が生成されます。

div1 = NaN : div2 = NaN
div1 == div2 : false
div1 == div1 : false
div2 == div2 : false
Double.NaN == Double.NaN : false
Float.NaN == Float.NaN : false

これらはすべてfalse.、浮動小数点数または倍精度数でこの演算 (ゼロによる除算) が許可されているのはなぜですか?


ちなみに、浮動小数点数(倍精度数)には、数値( )ではなく、正の無限大の無限大を表す値があることがわかります...NaN

4

6 に答える 6

61

つまり、Java の浮動小数点演算が基づいている IEEE-754 標準で指定されている方法です。

ゼロ除算 (またはオーバーフロー、アンダーフロー) でプログラムが停止したり、エラーが発生したりしないのはなぜですか? 数値の標準に「非数」(NaN) が含まれるのはなぜですか?

754 モデルは堅牢なプログラムを促進します。数値アナリストだけでなく、スプレッドシート ユーザー、データベース システム、さらにはコーヒー ポットも対象としています。NaN と無限大の伝播規則により、重要でない例外を消滅させることができます。同様に、段階的アンダーフローは、精度の範囲にわたってエラー プロパティを維持します。

例外的な状況に注意が必要な場合は、トラップを介してすぐに、またはステータス フラグを介して都合のよいときに調べることができます。トラップを使用してプログラムを停止できますが、回復不能な状況は非常にまれです。組み込みシステムやネットワーク エージェントにとって、単にプログラムを停止するという選択肢はありません。多くの場合、トラップは診断情報をログに記録するか、有効な結果を代用します。

フラグは、予測可能な制御フローと速度の両方を提供します。それらを使用するには、プログラマーが例外的な条件を認識している必要がありますが、フラグの粘着性により、プログラマーは必要になるまで例外的な条件の処理を遅らせることができます。

于 2012-10-18T12:16:32.150 に答える
17

それはIEEE 754がそれを定義した方法だからです。

浮動小数点 0.0 による除算は、分子が 0 であるかどうかに応じて、NaN または +/-Inf を生成します。

整数 0 による除算は IEEE 754 でカバーされておらず、例外が生成されます。 はまたはintを表すことができないため、エラーを示す他の方法はありません。NaNInf

INT例外の生成は、x86 マイクロプロセッサのゼロ除算によって生成される(ソフトウェア) に似ています。

于 2012-10-18T12:16:40.260 に答える
11

無限の彼方へ

class DoubleDivision {

    public static void main(String[] args) {
        System.out.println(5.0/0.0);
    }
}

上記のコードと、あなたが言及したスニペットはinfinity.

Java がDouble小数を表すために s を使用する理由。Binary は数値を完全に表現することはできず、近似値しか表現できないため、Java の double も表現できません。

限りなくゼロに近い数字を想像してみてください。微積分を知っている場合は、ゼロの極限を想像してください。変数はゼロから想像できるほど小さな距離に近づきますが、正確に等しくなることはありません。想像できますよね?Java が表現するのに非常に多くの精度が必要であると仮定すると0.0、適切な代替手段がないため、Java は諦めてそれを呼び出します。それがここで起こっていることです。ゼロに非常に近い数で割った通常の数は、基本的に無限大です。試してみてください: 5 / (10^-100).

セクションも参照してください:詳細については、数学エラーの特別な浮動小数点値:)

関連する質問: 1/0 ではエラーが発生するのに、1.0/0/0 では inf が発生するのはなぜですか

更新: セットにINT無限大と値がありませんが、NaNフロートには無限大とNaN値があります。(Java が従う IEEE 754 規格による)

于 2012-10-18T12:09:10.950 に答える
5

ゼロによる除算がある場合、コンピューターは結果の表現を数値として作成できません。コンピューターは、結果が数値ではないことを知らせる必要があります。

浮動小数点値の場合、数値を表さない32 ビット ( の場合float) と 64 ビット ( の場合) のビット パターンがいくつかあるため、特殊な非数値のセンチネル値を生成できます。 double-番号 ( NaN)。

一般的な 2 の補数スキーム (Java が必要とする) を使用する整数値の場合、すべての 32 ビット ( の場合int) および 64 ビット ( の場合long) のビット パターンは数値を表します。そのため、コンピュータはセンチネルを使用して問題を報告できません。何らかの方法で「帯域外」の問題を報告する必要があります。例外のスローは、Java で選択されたアウト オブ バンド メソッドです。

于 2012-10-18T12:16:02.250 に答える
3

Java は IEEE 754 標準に準拠しており、ゼロ除算の場合にデフォルトで返される値を定義しています。http://en.wikipedia.org/wiki/IEEE_754#Exception_handling

ゼロによる除算 (有限オペランドに対する演算は、1/0 または log(0) などの正確な無限の結果をもたらします) (デフォルトでは ±infinity を返します)。

于 2012-10-18T12:15:30.670 に答える