Javascript toFixed nicht gerundet

Ich verwende Javascript, um an einige Kontrollkästchen zu binden, und dietoFixed(2) wird nicht aufgerundet. Irgendwelche Ideen, warum es nicht rundet? Zum Beispiel, wenn die Nummer ist859.385 es wird nur angezeigt859.38 anstatt859.39.

Ich habe auch gelesen, dass dietoFixed Kann das anders sein, je nachdem welchen Browser du verwendest, weiß jemand, wie das umgeht, damit meine Javascript-Berechnungen mit meinen PHP-Berechnungen übereinstimmen?

<code>var standardprice = parseFloat($('#hsprice_'+this.id.split('_')[1]).val());
var price =  parseFloat($('#hprice_'+this.id.split('_')[1]).val());
var discount =  parseFloat($('#hdiscount_'+this.id.split('_')[1]).val());
var deposit =  parseFloat($('#hdeposit_'+this.id.split('_')[1]).val());

var currSprice = parseFloat($('#hTotalSprice').val());
var currPrice = parseFloat($('#hTotalPrice').val());
var currDiscount = parseFloat($('#hTotalDiscount').val());
var currDeposit = parseFloat($('#hTotalDeposit').val());

currSprice += standardprice;
currPrice += price;
currDiscount += discount;
currDeposit += deposit;

$('#lblTotalSprice').text('$'+addCommas(currSprice.toFixed(2)));
$('#lblTotalPrice').text('$'+addCommas(currPrice.toFixed(2)));
$('#lblTotalDiscount').text('$'+addCommas(currDiscount.toFixed(2)));
$('#lblTotalDeposit').text('$'+addCommas(currDeposit.toFixed(2)));

$('#hTotalSprice').val(currSprice.toFixed(2));
$('#hTotalPrice').val(currPrice.toFixed(2));
$('#hTotalDiscount').val(currDiscount.toFixed(2));
$('#hTotalDeposit').val(currDeposit.toFixed(2));
</code>
 David Winiecki09. Mai 2014, 19:44
Da 0,5 genau auf halber Strecke zwischen 0 und 1 liegt und Aufrundung nur eine Konvention ist, frage ich mich, wie wichtig es wirklich ist, ein bestimmtes Ergebnis zu garantieren. Um Ihren Code zu testen, benötigen Sie jedoch vorhersehbare Ergebnisse und Tests sind wichtig. Das ist also ein guter Grund.
 Pawel10. Juni 2016, 17:45
Meine Antwort auf eine ähnliche Frage hier:stackoverflow.com/a/37751946/2261514
 Noyo17. Mai 2015, 22:30
Hier ist ein Hinweis, warum die Rundung von.toFixed kann unintuitiv erscheinen:(0.1).toFixed(20) . (Beachten Sie, dass die IE-Implementierung das "intuitive" Ergebnis liefert, während andere Browser den standardkonformen Wert liefern.)

Antworten auf die Frage(16)

Vorschläge in anderen Antworten zu finden. Dabei habe ich festgestellt, dass ich immer noch nicht das erwartete Ergebnis erhalten habe. Da ich AngularJS für mein aktuelles Projekt verwende, überlege ich mir, ob AngularJS das gleiche Problem bereits zuvor gelöst hat und tatsächlich hat. Hier ist die Lösung, die sie verwenden und die für mich perfekt funktioniert:

<code>function toFixed(number, fractionSize) {
    return +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
}
</code>

Hier gefunden:AngularJS filters.js Quelle

 Steve Eynon26. Aug. 2015, 13:40
Dies ist identisch mitdiese Antwort außer AngularJS hat das Trailing nicht.toFixed()

die toFixed10 falsch macht. Kann sonst noch jemand?

Dank anblg undseine Antwort was mich auf Mozillas zeigtetoFixed10 () Methode.

Damit habe ich mir diesen kurzen Liner ausgedacht, der in der Tat alle hier genannten Fälle abdeckt ...

<code>function toFixed( num, precision ) {
    return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision);
}
</code>
 Codler23. Feb. 2018, 16:35
Dies behandelt keine doppelte Rundung. Das ist Antwort funktioniertstackoverflow.com/a/43998255/304894
 Hanna24. März 2016, 21:17
@ledlogictoFixed10 sieht aus wie es von blg hinzugefügt wurde, ruft es nurround10 und danntoFixed.
 Greenlandi28. Juli 2015, 08:33
Die Zahl 0,0000001 oder weniger ergibt NaN
 Slashback18. Juni 2014, 21:10
Ich mag das! Fügte deinen Einzeiler zu blgs Geige hinzu:jsfiddle.net/cCX5y/3
 ledlogic13. März 2015, 02:20
Was / Wo ist toFixed10? Bitte fügen Sie einen Link hinzu?
 Edward Sammut Alessi06. März 2018, 17:26
@mrts toFixed (89.684449, 2) ist richtig 89.68, es wäre nur 69, wenn es 89.685 <alle anderen irrelevanten Ziffern> wäre
 mrts01. Jan. 2018, 12:02
Nein, das ist immer noch ungenau,toFixed(89.684449, 2) sollte sein89.69, aber ist89.68.
 Benny Bottema24. Mai 2016, 10:19
@Johannes, ich habe Lodash zum Mix hinzugefügt:jsfiddle.net/cCX5y/35
 Geograph25. Apr. 2018, 14:26
AuftoFixed(0.000000015, 8) NaN holen. Für die richtige Antwort 0.00000002 benutze ich diese Funktionfunction round(v,d){return parseFloat(Math.round(v.toFixed(d+1)+'e'+d)+'e-'+d)};

Number.toFixed benahm sich seltsam. Ich sehe, dass die native Funktion unzuverlässig ist, was bedauerlich ist. Wenn ich die Antworten aus Neugierde durchschaue, sehe ich, dass sich die meisten * mit der Zahl nicht richtig verhalten35.855 als T.J. Crowder kommentierte jeden freundlich.

Vielleicht beantwortet dies Ihre Frage.

function toFixed(n,precision) {
    var match=RegExp("(\\d+\\.\\d{1,"+precision+"})(\\d)?").exec(n);
    if(match===null||match[2]===undefined) {
        return n.toFixed(precision);
        }
    if(match[2]>=5) {
        return (Number(match[1])+Math.pow(10,-precision)).toFixed(precision);
        }
    return match[1];
    }

Der reguläre Ausdruck teilt Ihre Nummer in eine Reihe von Zeichenfolgen wie in auftoFixed(35.855,2): ["35.855", "35.85", "5"]. Wenn die letzte Zahl (nach dem Präzisions-Cutoff) ist>=5, hinzufügenMath.pow(10, -precision) auf die gestutzte Zahl. Dies wird hinzufügen.01 Wenn Sie bei 2 Dezimalstellen abschneiden,.002 um 3, so weiter und so fort.

Ich weiß nicht, ob dies narrensicher ist, da es immer noch dezimale Berechnungen für Floats ausführt, die unvorhersehbar sein können. Ich kann sagen, dass es rundet35.855 bis zu35.86.

In ChrometoFixed() Runden:

<code>859.385 ==> 859.38
859.386 ==> 859.39
</code>

Wenn ich mich anschauedie ECMAScript 5th Edition Spezifikation für.toFixed() (Abschnitt 15.7.4.5), ich sehe es nicht explizit als Beschreibung der Rundung, obwohl es etwas ziemlich Stumpfes beschreibt, das möglicherweise von Chrome implementiert wurde.

Es scheint mir, dass, wenn Sie es mit expliziter Rundung steuern möchten, Sie wahrscheinlich die häufig vorgeschlagene Problemumgehung verwenden sollten:

<code>var roundedNum = (Math.round( num * 100 ) / 100).toFixed(2);
</code>

Dies garantiert, dass Sie eine vorhersehbare Rundung erhalten, wie Sie es gewohnt sind.

Arbeitsdemo hier:http://jsfiddle.net/jfriend00/kvpgE/

 mattbilson08. Aug. 2013, 17:33
Es wirdnormalerweise garantieren, dass Sie eine vorhersehbare Rundung erhalten. Jedoch wie erwähntin dieser Antwort Der Art und Weise, wie Javascript mit Dezimalstellen umgeht, kann nicht wirklich vertraut werden. Versuchen Sie es einfach mit 35.855 * 100 in der Chrome-Konsole ... Ich weiß, ich war auch schockiert! Das wird das bedeuten(Math.round( 35.855 * 100 ) / 100).toFixed(2) == 35.85   anstatt 35,86. In dieser anderen Antwort finden Sie Tipps ...

die Sie zusammen mit 35.855 probieren sollten, ist 1.005

Ich glaube nicht, dass die Lösung von Robert Messerle 1.005 bewältigt

Das Beispiel der Dezimalrundung hierhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round$ revision / 1383484 # Decimal_rounding konvertiert Zahlen in Exponentialschreibweise und scheint bessere Ergebnisse zu erzielen.

Ich habe hier eine Geige erschaffenhttp://jsfiddle.net/cCX5y/2/ das demos der gebürtigen robert messerle beispiel oben (genannttoFixedB) und der von Mozilla docs (genannttoFixed10).

Ich habe noch keine Nummer gefunden, die toFixed10 falsch macht. Kann sonst noch jemand?

 theycallmethesloth02. Jan. 2018, 17:39
Ich denke, Sie sind doppelt gerundet. (en.wikipedia.org/wiki/Rounding#Double_rounding). Jede Zahl wie 1.2345 rundet auf 1.23 und nicht auf 1.24
 mrts01. Jan. 2018, 12:05
Alle von ihnen sind ungenau,toFixed10(89.684449, 2) und andere sollten es sein89.69, aber ist89.68.
 Slashback18. Juni 2014, 21:09
Gute Geige und Link. Ich habe den Einzeiler von user2823670 hinzugefügt:jsfiddle.net/cCX5y/3
 Hanna29. März 2016, 19:06
Sieht aus wiediese Antwort funktioniert auch und enthält nicht den gesamten zusätzlichen Code.

<code>let TruncatedValueInString = ThenNumberYouWantToTruncate.toFixed(decPlaces + 1).slice(0, -1);
</code>

5 gehört nicht zur oberen Hälfte einer Ganzzahl, die angegebene Zahl wird abgerundet, wenn Sie solche Zahlen haben:

859.385.toFixed(2) // results in 859.38

Tatsächlich können Sie folgende Gleitkommazahlen (außer Null) anhängen:

859.3851.toFixed(2) // results in 859.39

Daher tendieren Entwickler dazu, Zahlen wie hinzuzufügen0.00000000001 damit es richtig gerundet wird und sich der Wert der Zahl nicht versehentlich ändert.

Also habe ich mir eine Funktion ausgedacht, die eine solche Zahl hinzufügt, abhängig davon, wie viele Stellen Ihre Gleitkommazahl festgelegt werden soll:

<code>    // both parameters can be string or number
    function toFixed(number, decimals) {
        var x = Math.pow(10, Number(decimals) + 1);
        return (Number(number) + (1 / x)).toFixed(decimals)
    }
    toFixed(859.385, 2) //results in 859.39
</code>
 Codler23. Feb. 2018, 16:36
Beste Antwort, die ich finden konnte! Einfach zu lesender Code und sogar doppeltes Runden!
 Edward Sammut Alessi06. März 2018, 17:32
toFixed(859.3844, 2) gibt859.39, sollte aber sein859.38

eine Zahl als Ausgabe, dann betrachten Sie dieMath.round() Technik in anderen Antworten.

Aber wenn du bekommen willsteine Zeichenfolge als Ausgabe zur Präsentation für einen Menschendann oftn.toLocaleString() ist hilfreicher alsn.toFixed().

Warum? Weil es auch Kommas oder Punkte zum Kopf großer Zahlen hinzufügt, die Menschen zum Lesen verwenden. Zum Beispiel:

<code>var n = 1859.385

n.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})

// Produces  1,859.39  in USA (locale en-US)
// Produces  1 859,39  in France (locale fr-FR)
// Produces  1.859,39  in Germany (locale de-DE)
</code>

Die Spezifikation sagt das beim Übergebenundefined Als erstes Argument wird das eigene Gebietsschema des Benutzers verwendet (wie vom Betriebssystem angegeben). Wie die verknüpfte Dokumentation zeigt, verwendet Mozilla in dieser Situation leider das Gebietsschema "en-US", das jedoch möglicherweise in Zukunft der Spezifikation entspricht.

dass 859.385 keine Darstellung als Float an einem Computer hat. Es wird als nächstmöglicher Wert gescannt = 859.3849999999991. Und das Runden dieses Werts auf 2 Stellen ist 859,38 und nicht 859,39.

Dies ist der Grund dafür, dass viele Programmiersprachen (insbesondere alte für den Handel, z. B. COBOL) BCD-Nummern (binär codierte Dezimalstellen) unterstützen, wobei jede Ziffer für sich in 4 Bits codiert wird (wie Hex ohne Verwendung von A-F).

Eine allgemeine Lösung für Preise: - Berechnen Sie in Cent / Penny und geben Sie NUMBER / 100 aus.

Eine Anmerkung zu anderen Lösungen (hier bereitgestellte Funktionen): Sie können für einige Zahlen hilfreich sein, scheitern jedoch meistens für z. 859,38499999.

das könnte helfen

<code>    tofix2Decimals=function(float){
        if(parseInt(float)==float)return float.toFixed(2);
        $decimals=/\.(\d+)/.exec(float)[1].length;
        $decimals=$decimals>=2?$decimals+1:3;
        float+=Math.pow(10,-$decimals);
        return float.toFixed(2);
    }
</code>
 T.J. Crowder07. Nov. 2013, 09:01
EinErläuterung könnte helfen.
 ncmathsadist03. Mai 2018, 19:43
Ein schöner und ausgefallener Ausflug zur verschleierten Eisbahn. Pfui.
<code>function roundup(num,dec){
    dec= dec || 0;
    var  s=String(num);
    if(num%1)s= s.replace(/5$/, '6');
    return Number((+s).toFixed(dec));
 }

 var n= 35.855
 roundup(n,2)
</code>

/ * Rückgabewert: (Number) 35.

 Sean the Bean21. Nov. 2013, 16:18
Dies ist die einzige Lösung, die ich gesehen habe und die sich vorhersehbar runden wird.
 T.J. Crowder07. Nov. 2013, 08:59
Probieren Sie es mit35.855.
 Mansiemans11. Feb. 2014, 13:06
Das einzige Problem ist, dass es nicht funktioniert, wenn eines der Dezimalstellen 5 ist und die Anzahl der zu rundenden Dezimalstellen höher ist als die Position dieser 5, z. Zusammenfassung (70,5, 2). Dies kann leicht verbessert werden, indem der reguläre Ausdruck in der replace-Anweisung in etwa wie folgt geändert wird: s.replace (/ (\ d {n}) 5 /, '$ 16'), wobei n gleich dem dec-Parameter ist. Wir müssen nur die 5 an der n + 1-Stelle hinter dem Dezimalpunkt ändern, wenn wir auf n Dezimalstellen runden. Stimmt das?

robuste Rundungsimplementierung. Es ist genauer, dass die meisten, wenn nicht alle Antworten hier sind.

 Steve Eynon26. Aug. 2015, 13:31
Diese MDM-Verbindung ist dietoFixed10() Methode, die in mehreren Antworten erwähnt wurde, die im letzten Jahr veröffentlicht wurden.

t. Sie können es an allen problematischen Zahlen testen. Javascript erlaubt eine Art von Präzision, deshalb habe ich es benutzt, um fast jede Zahl wie erwartet zu runden.

<code>function roundTo(n, digits) {
        if (digits === undefined) {
            digits = 0;
        }

        var multiplicator = Math.pow(10, digits);
        n = parseFloat((n * multiplicator).toFixed(11));
        return Math.round(n) / multiplicator;
    }
</code>
 Ivan Skalauh22. Mai 2018, 23:12
Umm der Kommentar ist irreführend, roundTo (89.684449, 2) sollte nicht 89.69 sein und ist legitim 89.68.

Du kannst den ... benutzenMath.round() die Zahl runden. Wenn Sie auf einen bestimmten Dezimalpunkt runden möchten, können Sie ein wenig Mathematik anwenden:

<code>var result=Math.round(original*100)/100
</code>
 InsOp16. Mai 2017, 12:03
Nein, das war nur ein Beispiel. einfügen für die100 Math.pow(10, decimalpoint) woherdecimalpoint ist die Anzahl der Gleitkommazahlen, die Sie aufrunden möchten
 T.J. Crowder07. Nov. 2013, 08:58
Beachten Sie, dass dies unzuverlässig ist. Probieren Sie es mit35.855Zum Beispiel, und Sie werden am Ende mit35.85 (nicht35.86).

anstatt der so vielen Hack Arounds.

<code>   x = 1859.385;
   x = x.toFixed(2);
   alert(x);
</code>

ergibt eine falsche Abrundung zB 1859.38 statt 1859.39

<code> x = 1859.385;
 x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
 alert(x);
</code>

ergibt eine korrekte Abrundung von 1.859,39

Das einzige Problem ist, dass das zurückgegebene Ergebnis eine Zeichenfolge mit Tausender-Komma-Trennzeichen ist und daher nicht für Berechnungen verwendet werden kann. Mit einem regulären Ausdruck, den ich vom Stapelüberlauf erhalten habe, um das Komma zu entfernen, ist das Endergebnis

<code> x = 1859.385;
 x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
 x=x.replace(/\,/g,'');
 alert(x);
</code>

das gibt jetzt 1859.39 zurück und kann für Berechnungen verwendet werden. Der Wert vor Regex, dh 1.859,39, kann für die HTML-Anzeige verwendet werden, während der nicht formatierte Wert 1859,39 für Berechnungen verwendet werden kann.

Versuche dies:

<code>Number.prototype.round = function(digits) {
    digits = Math.floor(digits);
    if (isNaN(digits) || digits === 0) {
        return Math.round(this);
    }
    if (digits < 0 || digits > 16) {
        throw 'RangeError: Number.round() digits argument must be between 0 and 16';
    }
    var multiplicator = Math.pow(10, digits);
    return Math.round(this * multiplicator) / multiplicator;
}

Number.prototype.fixed = function(digits) {
    digits = Math.floor(digits);
    if (isNaN(digits) || digits === 0) {
        return Math.round(this).toString();
    }
    var parts = this.round(digits).toString().split('.');
    var fraction = parts.length === 1 ? '' : parts[1];
    if (digits > fraction.length) {
        fraction += new Array(digits - fraction.length + 1).join('0');
    }
    return parts[0] + '.' + fraction;
}
</code>

Verwendungszweck:

<code>var n = 859.385;
console.log(n.round(2)); // 859.39
console.log(n.fixed(2)); // 859.39
console.log(n.round(4)); // 859.385
console.log(n.fixed(4)); // 859.3850
</code>
 Matveev Dmitriy05. Dez. 2014, 12:29
var n = 1.005; console.log(n.round(2)) gibt 1 nicht 1,01 zurück

Ihre Antwort auf die Frage