Warum löst Java beim Teilen durch 0.0 keine Ausnahme aus?

68

Ich habe Code, um die prozentuale Differenz zwischen 2 Zahlen zu berechnen - (oldNum - newNum) / oldNum * 100;- wobei beide Zahlen doubles sind. Ich hatte erwartet, dass ich eine Art Überprüfungs- / Ausnahmebehandlung hinzufügen muss, falls oldNum 0 ist. Als ich jedoch einen Testlauf mit Werten von 0.0 für oldNum und newNum durchführte, wurde die Ausführung fortgesetzt, als wäre nichts passiert und es wurde kein Fehler ausgegeben. Das Ausführen dieses Codes mit ints würde definitiv eine arithmetische Ausnahme für die Division durch Null verursachen. Warum ignoriert Java es, wenn es um doubles geht?

froadie
quelle
4
Gute Frage - die Inkonsistenz zwischen ganzzahligem und doppeltem Verhalten sorgt für Verwirrung und Ärger.
Steve B.
2
@ Raedwald - wenn man bedenkt, dass diese Frage 2 1/2 Jahre vor der von Ihnen verlinkten gestellt wurde, würde ich sagen, dass die Frage ein (mögliches) Duplikat dieser Frage ist :)
froadie

Antworten:

46

Das Ergebnis der Division durch Null ist mathematisch gesehen undefiniert , was mit einem float / double (als NaN- keine Zahl) ausgedrückt werden kann , es ist jedoch in keinem fundamentalen Sinne falsch.

Da eine Ganzzahl einen bestimmten numerischen Wert enthalten muss, muss beim Umgang mit ihnen ein Fehler auf die Division durch Null geworfen werden.

Kris
quelle
7
Genau. Dies ist in der Java-Sprachspezifikation hier definiert: java.sun.com/docs/books/jls/third_edition/html/…
Michael Myers
6
Ich denke, es sollte eine Ganzzahl geben.NaN
OscarRyz
13
@trinithis: Ihre Erklärung hat nichts mit dem Grund zu tun, warum es keine Integer.NaN gibt. Der Grund ist einfach, dass der IEEE-Standard für Gleitkomma-Arithmetik solche speziellen Werte vorschreibt, während der Quasi-Standard für ganzzahlige Arithmetik (Zweierkomplement) keine solchen speziellen Werte hat, so dass es den Implementierern überlassen bleibt, mit der Division durch Null umzugehen (Auslösen eines Interrupts) oder eine Ausnahme, die einen bestimmten Wert angibt oder das Ergebnis einfach undefiniert lässt).
Michael Borgwardt
2
@Kris: Genau genommen kann es nicht unendlich sein, weil lim (1 / x) sich von x -> 0+ und x -> 0- unterscheidet. Aber das ist ein kleiner Streitpunkt.
eaolson
8
x / 0 ist NICHT unendlich, das Ergebnis ist undefiniert. x / y tendiert gegen unendlich, wenn y gegen 0 tendiert. Entschuldigung für den Thread-Nekro.
So viele Goblins
110

Java floatund doubleTypen implementieren, wie so ziemlich jede andere Sprache (und so ziemlich jede Hardware-FP-Einheit), den IEEE 754- Standard für Gleitkomma-Mathematik, der die Division durch Null vorschreibt, um einen speziellen "Unendlichkeit" -Wert zurückzugeben. Das Auslösen einer Ausnahme würde tatsächlich gegen diesen Standard verstoßen.

Die Ganzzahlarithmetik (implementiert als Zweierkomplementdarstellung durch Java und die meisten anderen Sprachen und Hardware) ist unterschiedlich und weist keine speziellen Unendlichkeits- oder NaN-Werte auf. Daher ist das Auslösen von Ausnahmen dort ein nützliches Verhalten.

Michael Borgwardt
quelle
4
Die richtige Antwort auf diese Frage sollte dies sein. Ich musste wissen warum floatund doubleverursacht keine Ausnahmen. Vielen Dank.
Cengiz Can
1
Dies sollte die markierte richtige Antwort sein. Die Antwort, die derzeit als richtig markiert ist, beantwortet weder die Frage noch macht sie deutlich, dass Java IEEE 754
folgt.
5

Die Art und Weise, wie ein Double gespeichert wird, unterscheidet sich erheblich von einer int. Unter http://firstclassthoughts.co.uk/java/traps/java_double_traps.html finden Sie eine ausführlichere Erläuterung, wie Java mit Doppelberechnungen umgeht. Sie sollten sich auch über Gleitkommazahlen informieren, insbesondere über das Konzept von Not a Number (NaN) .

Wenn Sie mehr über die Gleitkommadarstellung erfahren möchten, empfehlen wir Ihnen, dieses Dokument zu lesen (Word-Format, sorry). Es befasst sich mit der binären Darstellung von Zahlen, die für Ihr Verständnis hilfreich sein kann.

Mike
quelle
4

Obwohl Java - Entwickler über die Doppel primitive Art und Know - DoubleKlasse, während Gleitkomma - Arithmetik zu tun zahlen sie nicht genug Aufmerksamkeit Double.INFINITY, NaN, -0.0und andere Regeln , die die arithmetischen Berechnungen mit ihnen regieren.

Die einfache Antwort auf diese Frage ist, dass sie nicht werfen ArithmeticExceptionund zurückkehren wird Double.INFINITY. Beachten Sie auch, dass der Vergleich x == Double.NaNimmer ausgewertet wird false, auch wenn er xselbst ein ist NaN.

Um zu testen, ob a xist NaN, sollte man den Methodenaufruf verwenden, um Double.isNaN(x)zu überprüfen, ob die angegebene Nummer NaN ist oder nicht. Dies ist sehr nah an NULLin SQL.

Es kann für Sie hilfreich sein.

Ziyapathan
quelle
4

Wenn durch Null geteilt (0 oder 0,00)

  1. Wenn Sie double durch 0 teilen, zeigt JVM Infinity an .

    public static void main(String [] args){ double a=10.00; System.out.println(a/0); }

    Konsole: Infinity

  2. Wenn Sie int durch 0 teilen, löst JVM eine arithmetische Ausnahme aus .

    public static void main(String [] args){ int a=10; System.out.println(a/0); }

    Konsole: Exception in thread "main" java.lang.ArithmeticException: / by zero

  3. Aber wenn wir int durch 0.0 teilen, zeigt JVM Infinity:

    public static void main(String [] args){ int a=10; System.out.println(a/0.0); }

    Konsole: Infinity

Dies liegt daran, dass JVM cast int automatisch in double eingibt, sodass anstelle von ArithmeticException unendlich wird.

Raman Gupta
quelle