[JAVA] Runden Sie das Ergebnis einer Bruchberechnung nicht einfach ab

Wenn Sie etwas programmieren, haben Sie möglicherweise gehört, dass "Gleitkommazahlen einen Fehler haben".

Aber ist dir das immer bewusst? Ich war mir dessen nicht bewusst und ging es durch.

Häufige Beispiele

Eines Tages musste das Einzahlungsguthaben des Benutzers auf 0,5% Zinsen abgerundet werden. Ich habe diesen Code geschrieben, weil ich dachte, es sei eine einfache Berechnung.

JavaScript


Math.floor(value * 1.005)

…… ** Das ist ein Fehler. ** **.

Lassen Sie uns versuchen, "1000" in "Wert" zu setzen. Ich habe das Gefühl, 0,5% zu 1000 zu addieren, ergibt 1005, aber in Wirklichkeit wird es 1004. Das obige Beispiel ist JavaScript, aber in den meisten wichtigen Sprachen ist das Ergebnis dasselbe. Probieren wir es aus.

Warum passiert das? Wenn Sie versuchen, "1000 * 1.005" so wie es ist auszugeben, wird es "1004.9999999999999" sein. Dieser Wert hat gerade nicht 1005 erreicht. Wenn Sie ihn also abschneiden, ist er 1004. Gleitkommazahlen können 1,005 nicht genau darstellen, daher scheint ein Fehler aufgetreten zu sein.

Achten Sie auf Kürzungen und Aufrundungen

Dieser Fehler kann sehr leicht auftreten. Alle folgenden Beispiele führen nicht zu den erwarteten Ergebnissen.

JavaScript


Math.floor(0.6 / 0.2) // 2
0.6 / 0.2             // 2.9999999999999996

JavaScript


//Verbrauchssteuer auf die nächste ganze Zahl aufgerundet
Math.ceil(900 * 1.08) // 973
900 * 1.08            // 972.0000000000001

JavaScript


let f = 0;
for (let i = 0; i < 10; i++) {
  f += 0.1;
}
Math.floor(f) // 0
f             // 0.9999999999999999

Es ist besser zu glauben, dass das Berechnungsergebnis einer Gleitkommazahl keine Ganzzahl ist.

Problemumgehung

Sie können dieses Problem vermeiden, indem Sie die Ergebnisse vor dem Runden auf eine ausreichend niedrige Ziffer runden.

JavaScript


//Auf die 4. Stelle gerundet
Math.floor((value * 1.005).toFixed(3))

Java


Math.floor(String.format("%.3f", value * 1.005))

PHP


floor(round($value * 1.005, 3))

Es ist möglicherweise nicht für Situationen geeignet, in denen strenge Berechnungen erforderlich sind, aber für die meisten Anwendungen sollte dies ausreichend sein. Möglicherweise möchten Sie die Math-Klasse so erweitern, dass sie von der gesamten Anwendung aus aufgerufen werden kann.

17/2/25 Nachtrag

Ich habe einen Kommentar erhalten. Mit dem Dezimaltyp ist es möglich, fehlerfreie Berechnungen ohne seltsame Implementierung durchzuführen. BigDecimal-Klassen können standardmäßig in Java verwendet werden, und JavaScript verfügt auch über eine Bibliothek mit dem Namen decimal.js. Es ist besser, so etwas zu verwenden, als es selbst zu implementieren. (Ergänzung bisher)

Zusammenfassung

Seien Sie vorsichtig bei der Berechnung von Brüchen.

Recommended Posts

Runden Sie das Ergebnis einer Bruchberechnung nicht einfach ab
Filtern Sie das Ergebnis von BindingResult [Spring]
Holen Sie sich das Ergebnis von POST in Java
Messen Sie einfach die Größe von Java-Objekten
Rückrechnung des Übergangs von Randoms internem Seed
Der ActiveSupport-Unterstrich ist nicht die inverse Konvertierung von camelize
Geben Sie jsessionid nicht beim ersten Zugriff
So zeigen Sie das Ergebnis des Ausfüllens des Formulars an