2013-08-08 7 views
11

Ich versuche herauszufinden, wie Ruby Zero Division behandelt. Ruby gibt basierend auf der Klasse unterschiedliche Ergebnisse zurück. Das habe ich ausprobiertWie behandelt Ruby Zero Division?

0/0  # => ZeroDivisionError: divided by 0  
1/0  # => ZeroDivisionError: divided by 0 
1.0/0 # => Infinity 
0.0/0.0 # => NaN 

Was passiert hier? Sollte ich nicht eine ZeroDivisionError für alle oben genannten Fälle bekommen?

Update Ist "Infinity" ein Standard-Datentyp, dann?

(1.0/0).class # => Float 
+4

Schwimmer sind nicht das gleiche wie Ints. Es sieht so aus, als ob Sie die Probleme bereits aufgezählt haben. Dinge wie NaN und Infinity sind typisch für Schwimmer. –

+0

@DaveNewton, aber es gibt keine Ausnahme im Falle von Floats, warum ist das der Fall? – ZX12R

+0

Da es sich bei der Gleitkommaarithmetik nicht um eine Ausnahme handelt; Es gibt einen wohldefinierten Wert ("Infinity" oder "NaN"). Siehe https://en.wikipedia.org/wiki/IEEE_floating_point#Exception_handling von Genes Link. –

Antwort

10

Ruby verfolgt nur die IEEE 754 Floating Point Standard. Diese Wikipedia-Seite ist nicht schlecht darin zu erklären, was Sie sehen. Viele moderne Sprachen verfolgen denselben Ansatz.

Intuitiv macht das Verhalten, das Sie sehen, Sinn. Im Allgemeinen

1/<small number> = <big number> 

deshalb im Grenzfall,

1/0 -> Infinity and similarly -1/0 -> -Infinity 

Infinity ist eine Konstante, die durch das Gleitkomma-Subsystem verstanden. Auf der anderen Seite

0/<any non-zero> = 0 

So haben wir einen Konflikt auf 0/0. Sollte es Null oder Unendlich sein? Die IEEE-Standardantwort ist "Not a Number", die NaN Sie sehen, eine andere Gleitkommakonstante. Die Konstanten NaN und plus oder minus Infinity propagieren durch Ausdrücke in einer Weise, die auch Sinn ergibt. Zum Beispiel:

Infinity + <any (necessarly finite) number> = Infinity 

und

<any number> + NaN = NaN 

Und noch interessanter ist:

1/Infinity = 0 

Welche können Sie selbst ausprobieren:

irb(main):005:0> 1.0/(1.0/0.0) 
=> 0.0 

Auf diese Weise wird eine Gleitkomma-Berechnung kann weiter, auch wenn es ist übergelaufen oder durch Null geteilt worden und erzeugt immer noch eine einigermaßen informative Antwort (obwohl, nachdem Sie den Standard gut kennen, Sie sehen werden, dass sich auf die Antwort zu verlassen, in der Regel eine schlechte Idee ist).

Dies ist bei weitem nicht das einzige Verhalten, das der Standard bietet. Andere können ausgewählt werden. Aber Ruby macht das für dich. Die Quelldatei numeric.c, Funktion Init_Numeric, richtet den Host-Prozessor so ein, dass Division durch Null Unendlichkeiten fortpflanzt. Andere Sprachen treffen möglicherweise andere Möglichkeiten, um beispielsweise eine Ausnahme zu erzeugen.

+7

Ich würde empfehlen, tatsächliche Informationen in Antworten und nicht nur einen Link zu integrieren. –

+0

Um. Es tut uns leid. Die Information ist, dass es den IEEE 754 Standard verfolgt. Jeder Programmierer sollte diesen Standard in seiner ganzen Breite kennen. Wenn ich hier Schnipsel zitiere, wird der Leser diese Gelegenheit verpassen. – Gene

+4

Link-Only-Antworten sind jedoch nicht wirklich in Ordnung. Verstecke dich nicht hinter "sie müssen das Ganze selbst lesen, um die zwei Sätze zu zeigen, die nötig sind, um die eigentliche Frage zu erklären." Heben Sie stattdessen die Notwendigkeit hervor, über die Oberflächenniveau hinaus zu verstehen * und * die spezifische Frage zu beantworten. –

7

Das Verhalten für Gleitpunkte spiegelt den Standard in IEEE 754:

  • Ungültige Operation (z.B. Quadratwurzel einer negativen Zahl) (liefert QNaN Standard).
  • Division durch Null (eine Operation mit endlichen Operanden ergibt ein genau unendliches Ergebnis, z. B. 1/0 oder log (0)) (gibt standardmäßig ± unendlich zurück).

Die Entscheidung, einen Laufzeitfehler für Integer-Division durch Null zu implementieren, ist in vielen anderen Sprachen auch wie Java, C++, Python gemeinsam. Python ruft tatsächlich auch den Fehler ZeroDivisionError auf.

Aus den Gründen für diese Klassifizierungen und Verhaltensweisen siehe sawa's answer.

4

Der Punkt ist, dass ein Schwimmer einen Rundungsfehler hat. Ein Gleitkomma 0.0 drückt nicht unbedingt die exakte Null oder 0,0 im mathematischen Sinne aus, sondern ist repräsentativ für alle Zahlen, die bei gegebener Genauigkeit auf 0.0 gerundet würden. Division durch genau 0 ist nicht mathematisch definiert, aber die Division durch 0.0 hätte die Gefahr, einen Fehler zurückzugeben, wenn der Divisor zufällig einen von Null verschiedenen Absolutwert hat, der klein genug ist, um auf 0.0 gerundet zu werden. Sie möchten nicht, dass ein Programm plötzlich einen Fehler zurückgibt, wenn der Absolutwert des Divisors klein ist, wenn er nicht Null ist. Im Fall von Floats ist es sicherer, wenn das System der Division durch 0.0 eine bestimmte Nummer zuweist, statt sie zu verbieten. Aber diese Zahl kann nicht normal ausgedrückt werden, daher wird NaN oder Infinity zugewiesen. Was irreführend ist, ist, dass die Unendlichkeit nicht im mathematischen Sinn unendlich ist. Es bedeutet nur "eine Zahl größer als jede andere Zahl, die in diesem System ausgedrückt werden kann." Das erklärt den Fall:

1.0/0.0 # => Infinity 
0.0/0.0 # => NaN 

Wenn ein Argument zu / ist ein Schwimmer, Rubin Typ wirft den anderen zu schweben, so

1/0.0 
1.0/0 

die gleiche wie 1.0/0.0 wäre.

Auf der anderen Seite enthält die Ganzzahl 0 keinen Fehler und ist genau Null, so dass es keine solche Gefahr gibt. Es ist sinnvoller, einen Nullteilungsfehler zu erzeugen. Das erklärt

1/0 # => Error 
0/0 # => Error