web-dev-qa-db-ja.com

浮動小数点(または倍精度)数でゼロによる除算がJava.lang.ArithmeticExceptionをスローしないのはなぜですか:Java

次の文は、明らかなようにJava.lang.ArithmeticException: / by zeroをスローします。

System.out.println(0/0);

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

ただし、次の場合はdoes n'tJava.lang.ArithmeticException: / by zeroなどの例外をスローします。

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

Infinityが表示されます。

次の文は、例外なしでNaN(非数)を生成します。

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

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


同様に、次のステートメントdo n'tは例外をスローします。

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)...

55
Tiny

要するに、それがIEEE-754標準で指定されている方法であり、これがJavaの 浮動小数点演算 の基になっています。

ゼロによる除算(またはオーバーフロー、アンダーフロー)がプログラムを停止またはエラーをトリガーしないのはなぜですか?数値の標準に「not-a-number」( NaN)?

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

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

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

57
Bill the Lizard

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

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

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

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

16
Alnitak

無限とその先へ

_class DoubleDivision {

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

上記のコードと、あなたが言及したスニペットはinfinityを与えます。

なぜJavaはDoublesを使用して小数を表します。バイナリは数値を完全に表すことはできません。

信じられないほどゼロに近い数を想像してください。計算を知っているなら、ゼロの限界を想像してください。変数は、ゼロに近づくと想像できるほど小さい距離になりますが、正確に等しくなることはありません。想像できますよね?さて、数値はJavaを表現するために非常に高い精度を必要としますが、適切な代替手段がないためあきらめて_0.0_と呼びます。それがここで起こっていることです。ゼロに近い非常に近い数で割った通常の数は、基本的に無限大です。試してください:5 / (10^-100)

次のセクションも参照してください:特別な浮動小数点値at Math Errors 詳しくは:)

関連質問: なぜ1/0はエラーを与えるが、1.0/0/0はinfを与えるのか

更新:INTには無限大とNaN値がありませんが、floatには無限大とNaN値があります。 (IEEE 754標準によると、Javaが続きます)

11
Mukul Goel

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

浮動小数点値の場合、32ビット(floatの場合)および64ビット(doubleの場合)ビットパターンがあるため、特別な非数センチネル値を生成できます。数値を表さないため、非数値(NaN)として解釈できます。

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

5
Raedwald

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

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

3
Peter Lawrey
import Java.util.Scanner;

public class Division {

    public static void main(String[] args) {
        int a, b;
        float result;

        Scanner input = new Scanner(System.in);
        System.out.println("Enter value for a : ");
        a = input.nextInt();

        System.out.println("Enter value for b : ");
        b = input.nextInt();

        try {
            /* here we used "if clause" because result will be in float
             note: Here result is in float, so JVM Cant Catch Exception.
             if we Try to Divide with Zero with Float Values It gives Output as
             Divided by Zero is Infinity */
            if (b != 0) {
                result = (float) a / b;
                System.out.println("Result of " + a + " divided by " + b + " is : " + result);
            } else // here result will be in integer so Jvm can easily Catch The Exception
            {
                result = a / b;
            }
        } catch (ArithmeticException e) {
            System.out.println("Sorry Division By Zero Is Not Possible");
        }
    }
}

/* Ouput :
Enter value for a :2
Enter value for b : 7
Result of 2 divided by 7 is : 0.2857143 */

 /* Ouput :
Enter value for a : 16
Enter value for b : 0
Sorry Division By Zero Is Not Possible */
0
sandeep16