Dieser Artikel wurde ursprünglich auf David Kayes Blog veröffentlicht
Ich fand Rundungsfehler in Number (). Tofixed () in allen JavaScript -Umgebungen, die ich ausprobiert habe (Chrome, Firefox, Internet Explorer, Brave und Node.js). Überraschenderweise ist das Fix sehr einfach. Lesen Sie weiter ...
Beim Ändern einer digitalen Formatierungsfunktion, die dieselbe Funktion wie intl.numberformat#format () ausführt, fand ich in dieser Version in tofixed () einen Rundungsfehler.
(1.015).toFixed(2) // 返回 "1.01" 而不是 "1.02"
Der fehlgeschlagene Test befindet sich hier in Zeile 42. Ich habe es erst im Dezember 2017 gefunden, was mich dazu veranlasste, nach anderen Problemen zu suchen.
Siehe meinen Tweet zu dieser Frage:
Es gibt einen langen Fehler der Fehlerberichterstattung bei der Verwendung von tofixed ().
Hier sind einige kurze Beispiele für Stackoverflow -Probleme zu diesem Problem:
Normalerweise weisen diese auf a a Fehler eines -Werges hin, aber kein Bereich oder Wertemuster, die das Fehlerergebnis zurückgeben (zumindest habe ich es nicht gefunden Ich hätte vielleicht etwas verpasst). Auf diese Weise können Programmierer sich auf kleine Probleme konzentrieren und keine größeren Muster sehen. Ich beschuldige sie nicht dafür.
unerwartete Ergebnisse, die auf der Eingabe basieren, müssen aus dem gemeinsam genutzten Modus in der Eingabe stammen. Anstatt die Spezifikation von Number (). Tofixed () zu überprüfen, habe ich mich auf das Testen mit einer Reihe von Werten konzentriert, um festzustellen, wo die Fehler in jeder Serie erscheinen.
Ich habe die folgende Testfunktion erstellt, um eine tofixed () -Operation auf einer Reihe von Ganzzahlen von 1 nach MaxValue durchzuführen und jeder Ganzzahl eine Dezimalzahl von wie 0,005 hinzuzufügen. Der Parameter fester (zahlenstellen) von tofixed () wird basierend auf der Länge des Dezimalwerts berechnet.
(1.015).toFixed(2) // 返回 "1.01" 而不是 "1.02"
Das folgende Beispiel führt eine Operation von Ganzzahlen 1 bis 128 aus, fügt für jede Ganzzahl eine Dezimalzahl von 0,015 hinzu und gibt ein "unerwartete" Array von Ergebnissen zurück. Jedes Ergebnis enthält gegeben, erwartete und tatsächliche Felder. Hier verwenden wir dieses Array und drucken jeden Element.
function test({fraction, maxValue}) { fraction = fraction.toString() var fixLength = fraction.split('.')[1].length - 1 var last = Number(fraction.charAt(fraction.length - 1)) var fixDigit = Number(fraction.charAt(fraction.length - 2)) last >= 5 && (fixDigit = fixDigit + 1) var expectedFraction = fraction.replace(/[\d]{2,2}$/, fixDigit) return Array(maxValue).fill(0) .map(function(ignoreValue, index) { return index + 1 }) .filter(function(integer) { var number = integer + Number(fraction) var actual = number.toFixed(fixLength) var expected = Number(number + '1').toFixed(fixLength) return expected != actual }) .map(function(integer) { var number = Number(integer) + Number(fraction) return { given: number.toString(), expected: (Number(integer.toFixed(0)) + Number(expectedFraction)).toString(), actual: number.toFixed(fixLength) } }) }
Für diese Situation gibt es 6 unerwartete Ergebnisse.
test({ fraction: .015, maxValue: 128 }) .forEach(function(item) { console.log(item) })
Ich habe festgestellt, dass dieser Fehler drei Teile enthält:
Zum Beispiel für Ganzzahlen 1 bis 128 (Wert) .Tofixed (2) verwendet verschiedene 3 Dezimalstellen, die in 5 enden, was zu den folgenden Ergebnissen führt:
Diejenigen, die mehr über binäre und schwimmende Punktmathematik wissen, können die Grundursache möglicherweise schließen. Ich überlasse dies dem Leser als Übung.
behoben durch mehr als ein Dezimaler , um den Wert zu beheben, wird immer korrekt abgerundet; Sowohl der Test als auch die Polyfill verwenden dieses Wissen für Korrektheitsprüfungen.
Dies bedeutet, dass alle tofixierten () -implementierungen eine einfache Lösung haben: Wenn der Wert eine Dezimalzahl enthält, appendieren Sie "1" bis zum Ende der String -Version des zu geänderten Werts. Dies ist möglicherweise nicht "mit den Spezifikationen konform", aber wir werden die erwarteten Ergebnisse erzielen, ohne die niedrigere Ebene an binären oder schwimmenden Punkten erneut zu besuchen zu müssen.
Bevor alle Implementierungen geändert werden, können Sie, wenn Sie dazu bereit sind, dies zu tun (nicht jeder möchte es), mit der folgenden Polyfill überschüssig ().
<code>Object { given: "1.015", expected: "1.02", actual: "1.01" } Object { given: "4.015", expected: "4.02", actual: "4.01" } Object { given: "5.015", expected: "5.02", actual: "5.01" } Object { given: "6.015", expected: "6.02", actual: "6.01" } Object { given: "7.015", expected: "7.02", actual: "7.01" } Object { given: "128.015", expected: "128.02", actual: "128.01" }</code>
Führen Sie den Test erneut aus und überprüfen Sie, ob die Ergebnislänge Null ist.
(1.005).toFixed(2) == "1.01" || (function(prototype) { var toFixed = prototype.toFixed prototype.toFixed = function(fractionDigits) { var split = this.toString().split('.') var number = +(!split[1] ? split[0] : split.join('.') + '1') return toFixed.call(number, fractionDigits) } }(Number.prototype));
oder führen Sie einfach die erste Konvertierung aus, die diesen Artikel startet.
test({ fraction: .0015, maxValue: 516 }) // Array [] test({ fraction: .0015, maxValue: 516 }).length // 0
Danke fürs Lesen!
Die Methode nummer.toFixed () in JavaScript wird verwendet, um Zahlen mithilfe von Festpunktnotation zu formatieren. Es gibt eine String -Darstellung einer Zahl zurück, die keine exponentielle Darstellung verwendet und genau die angegebene Anzahl von Ziffern nach dem Dezimalpunkt aufweist. Bei Bedarf ist die Zahl abgerundet und die Ergebniszeichenfolge hat nach der Länge einen Dezimalpunkt.
Aufgrund der Art und Weise, wie JavaScript binäre schwimmende Punktzahlen verarbeitet, liefert die Methode der Nummer. JavaScript verwendet binäre schwimmende Punktzahlen, die nicht alle Dezimalerdezimalstellen genau darstellen können. Diese Ungenauigkeit kann zu unerwarteten Ergebnissen führen, wenn die Zahl unter Verwendung der Zahl der Zahl (tofixed () auf eine bestimmte Dezimalzahl gerundet ist.
Eine Möglichkeit, Rundungsfehler in der Nummer zu beheben. Diese Funktion kann die Eigenschaften der digitalen Verarbeitung von JavaScript berücksichtigen und genauere Ergebnisse liefern. Sie können beispielsweise eine Funktion verwenden, die die Zahl mit einer Leistung von 10 multipliziert, sie auf die nächste ganze Zahl rundet und sie durch die gleiche Leistung von 10 unterteilt.
nein, die Zahl.Tofixed () -Methode kann nur mit numerischen Werten verwendet werden. Wenn Sie versuchen, es mit einem nicht numerischen Wert zu verwenden, werfen JavaScript einen Typeerror. Wenn Sie diese Methode mit einem Wert verwenden müssen, der möglicherweise keine Zahl ist, sollten Sie zuerst überprüfen, ob der Wert eine Zahl ist.
nummer.toFixed () und anderen Rundungsmethoden ist normalerweise vernachlässigbar. Wenn Sie jedoch eine Menge Vorgänge ausführen, kann die Verwendung einer benutzerdefinierten Rundungsfunktion etwas schneller sein als die Anzahl der Nummer.Tofixed ().
Nein, die Zahl.Tofixed () -Methode kann nur maximal 20 Dezimalstellen runden. Wenn Sie versuchen, auf mehr als 20 Dezimalstellen zu runden, werfen JavaScript ein Rangelein.
number.tofixed () Methode verarbeitet negative Zahlen genauso wie mit positiven Zahlen. Es rundet den Absolutwert der Zahl auf die angegebene Anzahl von Dezimalstellen und fügt ein negatives Vorzeichen hinzu.
Ja, die Methode der Nummer. Da verschiedene JavaScript -Motoren die Zahlen unterschiedlich verarbeiten, sind die Ergebnisse in allen Umgebungen möglicherweise nicht genau gleich.
Wenn Sie keine Argumente an die Nummer übergeben. Dies bedeutet, dass es die Nummer auf die nächste Ganzzahl rundet.
Ja, Sie können die Methode der nummer.tofixed () mit großen Zahlen verwenden. Denken Sie jedoch daran, dass JavaScript nur genau Zahlen bis zu 2^53 - 1 darstellen kann. Wenn Sie versuchen, die Methode der Nummer zu verwenden.
Das obige ist der detaillierte Inhalt vonNumber (). Tofixed () Rundungsfehler: defekt, aber fixierbar. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!