Frage

Warum in JavaScript Rückkehr 49.90 % 0.10 0.09999999999999581? Ich erwartete es 0 sein.

War es hilfreich?

Lösung

Da JavaScript verwendet Punkt math floating Fehler, die immer führt zu runden.

Wenn Sie ein genaues Ergebnis mit zwei Dezimalstellen, multiplizieren Sie Ihre Zahlen mit 100 vor der Operation und dann teilen danach wieder:

var result = ( 4990 % 10 ) / 100;

Runde, wenn nötig.

Andere Tipps

Javascript die Anzahl wird mit „IEEE doppelter Genauigkeit“, um die Werte zu speichern. Sie sind nicht in der Lage genau alle Dezimalzahlen zu speichern. Das Ergebnis ist nicht Null, da der Rundungsfehler, wenn die Dezimalzahl in Binär-Umwandlung.

49.90 = 49.89999999999999857891452848...
 0.10 =  0.10000000000000000555111512...

So Boden (49,90 / 0,10) nur 498, und der Rest wird 0,09999 sein ....


Es scheint, dass Sie Zahlen verwenden Menge von Dollar zu speichern. Sie diese nicht tun, als Gleitkommaoperationen propagieren und den Rundungsfehler verstärken. Speichern Sie die Zahl als Menge von Cent statt. Integer kann genau dargestellt werden, und 4990 % 10 0 zurück.

Ursache

Gleitpunkt können alle genau dezimal nicht speichern Werte. Also, wenn Gleitkomma-Formaten wird es immer Fehler auf den Eingangswerten Rundung. Die Fehler an den Eingängen natürlich Ergebnisse zu Fehlern am Ausgang. Im Fall einer diskreten Funktion oder Bediener kann sich um den Punkt, ein großer Unterschied auf dem ausgegeben werden, wo die Funktion oder Betreiber diskret ist. Der Modula Operator ist diskret und Ihr Fall ist eindeutig ein Beispiel für dieses Problem.

Eingang und Ausgang für Gleitkommawerte

Also, wenn Gleitkommavariablen verwenden, sollten Sie immer dessen bewusst sein. Und was Ausgabe, die Sie aus einer Berechnung soll mit schwimmenden Punkte sollten immer mit dieser formatiert / konditioniert werden vor der Anzeige im Auge behalten.
Wenn nur stetige Funktionen und Operatoren verwendet werden, häufig wird auf die gewünschte Präzision Rundung tun (nicht truncate). Standardformatierung zu konvertieren schwimmt auf String verwendeten Funktionen wird dies in der Regel für Sie tun.
Um eine korrekte Ausgabe auf Basis der erwarteten Genauigkeit der Eingänge zu haben und die gewünschte Genauigkeit des Ausgangs, sollten Sie auch

  • Rund Eingänge zu der erwarteten Präzision oder stellen Sie sicher, können keine Werte mit höherer Genauigkeit eingegeben werden.
  • einen kleinen Wert an die Ausgänge hinzufügen vor dem Runden / Formatierung ihnen, das kleiner ist als oder gleich 1/4 der gewünschte Präzision und größer als die maximal zu erwartenden Fehlern verursacht durch Fehler bei der Eingabe und bei der Berechnung Rundung. Wenn das nicht möglich ist, ist die Kombination aus der Präzision des verwendeten Datentypen nicht genug, um die gewünschten Ausgang Präzision für Ihre Berechnung zu liefern.

Diese 2 Dinge sind oft nicht getan und in den meisten Fällen die verursachten Unterschiede durch sie nicht zu klein machen für die meisten Anwender wichtig zu sein, aber ich hatte bereits ein Projekt, bei dem Ausgang von den Benutzern nicht ohne diese Korrekturen angenommen wurde.

Diskrete Funktionen oder Operatoren (wie Modula)

Wenn diskrete Operatoren oder Funktionen beteiligt sind, könnten zusätzliche Korrekturen erforderlich sein, die Ausgabe, um sicherzustellen, wie erwartet. Abgerundet und das Hinzufügen von kleinen Korrekturen vor dem Runden kann das Problem nicht lösen.
Eine spezielle Überprüfung / Korrektur auf Zwischenberechnungsergebnisse unmittelbar nach der diskreten Funktion oder Operator Anwendung erforderlich sein könnte.

Sonderfall dieser Frage

In diesem Fall erwarten Sie die Eingabe mit einer gewissen Genauigkeit, so ist es möglich, eine korrekte Ausgabe für Auswirkungen von Rundungsfehlern, die viel kleiner ist als die gewünschte Präzision sind.

Wenn wir die Genauigkeit Ihres Datentypen sagen ist e.
Ihre Eingaben werden nicht als die Werte gespeichert werden a und b Sie eingegeben haben, aber als * (1 +/- e) und b * (1 +/- e)
Das Ergebnis einer Division a * (1 +/- e) von b * (1 +/- e) würde in (a / b) (1 +/- 2e).
Die Modula-Funktion hat, um das Ergebnis gestutzt und mehrfach wieder. So das Ergebnis wird sein, (a / b
b) (1 +/- 3e) = a (1 +/- 3e) in einem Fehler eines * 3e führt.
Der Mod fügt eine * e auf den möglichen Fehler eines * 3e aufgrund der Subtraktion von zwei Werten mit einem möglichen Fehler eines * 3e und ein * e.
So sollten Sie prüfen, ob die insgesamt möglichen Fehler a * 4e kleiner als die gewünschten Genauigkeit sind und wenn diese Bedingung und das Ergebnis unterscheidet mich mehr erfüllt ist nicht von b als die maximal möglichen Fehlern, können Sie es sicher durch 0 ersetzen.

Besser vermeiden, das Problem

Es ist oft effizienter, diese Probleme zu vermeiden, indem sie Datentypen (Integer oder Festkommaformate) für Berechnungen wie diese verwendet, die den erwarteten Eingabefehler ohne Rundung speichern kann. Ein Beispiel dafür ist, dass Sie nie Gleitkommazahlen für finanzielle Berechnungen verwenden soll.

Schauen Sie sich auf Gleitpunkte und seine Nachteile - eine Zahl wie 0.1 kann nicht sein, korrekt als Gleitkomma gespeichert, so wird es immer solche Probleme. Nehmen Sie Ihre Zahlen * 10 oder * 100 und tun, die Berechnungen mit ganzen Zahlen statt.

http://en.wikipedia.org/wiki/Modulo_operation Seien Sie nicht ist wütend Modulo mit ganzen Zahlen verwendet ^^ So Gleitkommawerten einige Fehler occure.

Dies ist keine perfekte Lösung, aber es funktioniert.

function format_float_bug(num)
{
   return parseFloat( num.toFixed(15) ); 
} 

Sie können wie folgt verwenden,

format_float_bug(4990 % 10);

da unten Nummer (49,89999999999999857891452848) ersten 15 Dezimalstellen sind wie 9999999

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top