Warum dieser Code 7.30 - 7.20
in Rubin zurückkehrt 0.0999999999999996
, nicht 0.10
?
Aber wenn ich schreibe 7.30 - 7.16
zum Beispiel, alles wird gut, ich bekomme 0.14
.
Was ist das Problem, und wie kann ich es lösen?
Warum dieser Code 7.30 - 7.20
in Rubin zurückkehrt 0.0999999999999996
, nicht 0.10
?
Aber wenn ich schreibe 7.30 - 7.16
zum Beispiel, alles wird gut, ich bekomme 0.14
.
Was ist das Problem, und wie kann ich es lösen?
Das Problem besteht darin, dass einige Zahlen, die wir leicht in Dezimalzahlen schreiben können, keine exakte Darstellung in dem speziellen Fließkommaformat haben, das von der aktuellen Hardware implementiert wird. Um es salopp auszudrücken: Alle ganzen Zahlen haben eine exakte Darstellung, aber nicht alle Brüche, denn normalerweise speichern wir den Bruch mit einem 2**e
Exponent. Sie haben also 3 Möglichkeiten:
Runden Sie entsprechend ab. Das ungerundete Ergebnis ist immer sehr, sehr knapp, so dass ein gerundetes Ergebnis immer "perfekt" ist. Dies ist, was Javascript tut und viele Menschen nicht einmal erkennen, dass JS tut alles in Gleitkomma.
Verwenden Sie Festkommaarithmetik. Ruby macht dies wirklich einfach; es ist eine der wenigen Sprachen, die nahtlos von Fixnum zur Klasse Bignum wechselt, wenn die Zahlen größer werden.
Verwenden Sie eine Klasse, die für die Lösung dieses Problems konzipiert ist, wie BigDecimal
Um das Problem genauer zu betrachten, können wir versuchen, Ihre "7,3" in Binärform darzustellen. Der 7-Teil ist einfach, 111, aber wie machen wir .3? 111,1 ist 7,5, zu groß, 111,01 ist 7,25, kommt näher. Es stellt sich heraus, dass 111,010011 die "nächstkleinere Zahl" ist, 7,296875, und wenn wir versuchen, die fehlende 0,003125 aufzufüllen, finden wir schließlich heraus, dass es einfach 111,0100110011001100110011 ist... für immer, nicht darstellbar in unserer gewählten Kodierung in einer endlichen Bitfolge.
Das Problem ist, dass Gleitkomma ist ungenau . Sie können das Problem lösen, indem Sie Rational, BigDecimal oder einfach nur ganze Zahlen verwenden (wenn Sie z. B. Geld speichern möchten, können Sie die Anzahl der Cents als int speichern, anstatt die Anzahl der Dollar als float).
BigDecimal kann jede Zahl, die eine endliche Anzahl von Ziffern zur Basis 10 hat, genau speichern und rundet Zahlen, die das nicht tun (so sind drei Drittel nicht ganz).
Rational kann jede rationale Zahl genau speichern und kann überhaupt keine irrationalen Zahlen speichern.
Interessant ist, dass eine Zahl, die in einer Basis nur wenige Nachkommastellen hat, in einer anderen Basis in der Regel sehr viele Nachkommastellen hat. So sind beispielsweise unendlich viele Dezimalstellen erforderlich, um 1/3 (=0,3333...) in der Basis 10 auszudrücken, aber nur eine Dezimalstelle in der Basis 3. In ähnlicher Weise braucht man viele Dezimalstellen, um die Zahl 1/10 (=0,1) zur Basis 2 auszudrücken.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.