Vermisse ich hier etwas?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Warum wird.toFixed()
eine Zeichenfolge zurückgegeben?
Ich möchte die Zahl auf 2 Dezimalstellen runden.
Vermisse ich hier etwas?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Warum wird.toFixed()
eine Zeichenfolge zurückgegeben?
Ich möchte die Zahl auf 2 Dezimalstellen runden.
Antworten:
Es gibt eine Zeichenfolge zurück, da 0.1 und Potenzen davon (die zum Anzeigen von Dezimalbrüchen verwendet werden) in binären Gleitkommasystemen nicht darstellbar sind (zumindest nicht mit voller Genauigkeit).
Zum Beispiel ist 0,1 wirklich 0,10000000000000000555511151231257827021181583404541015625 und 0,01 ist wirklich 0,01000000000000000020816681711721685132943093776702880859375. (Danke, BigDecimal
dass du meinen Standpunkt bewiesen hast .:-P)
Daher ist die Ausgabe als Zeichenfolge (ohne Dezimal-Gleitkomma- oder rationalen Zahlentyp) die einzige Möglichkeit, die Genauigkeit genau auf die für die Anzeige erforderliche Genauigkeit zu bringen.
toFixed
handelt sich um eine Formatierungsfunktion, die ausschließlich dazu dient, eine Zahl in eine Zeichenfolge umzuwandeln und sie mit der angegebenen Anzahl von Dezimalstellen zu formatieren. Der Grund, warum eine Zeichenfolge zurückgegeben wird, liegt darin, dass eine Zeichenfolge zurückgegeben werden soll. Wenn sie toStringFixed
stattdessen benannt würde, wäre OP über die Ergebnisse nicht überrascht. Das einzige Problem hierbei ist, dass OP erwartet hat, dass es so funktioniert Math.round
, ohne die JS-Referenz zu konsultieren.
Number.prototype.toFixed
ist eine Funktion zum Formatieren einer Zahl vor dem Ausdrucken. Es ist aus der Familie der toString
, toExponential
und toPrecision
.
Um eine Zahl zu runden, gehen Sie folgendermaßen vor:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Oder wenn Sie eine " native-like " -Funktion wünschen , können Sie den Prototyp erweitern:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256 //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
Beachten Sie jedoch , dass die Verschmutzung des Prototyps beim Schreiben eines Moduls als schlecht angesehen wird, da Module keine Nebenwirkungen haben sollten. Also, für ein Modul verwenden , um die erste Funktion .
type Number
. Die Sache ist, dass +(anyValue)
immer eine Zahl zurückgegeben wird - z. +("45")
kehrt zurück 45
, +(new Number(42))
kehrt zurück 42
. Es ist ein bisschen so, als würde man die Funktion stark tippen. Wenn Sie es sich zur Gewohnheit machen, können Sie viele Fehler vermeiden :)
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
ist nicht 42.01
, es ist ~42.0099999999999980
. Grund: Die Nummer 42.01
existiert nicht und wird auf die nächste vorhandene Nummer gerundet. Übrigens, prüfen Sie die Nummern, indem Sie toPrecision(18)
sie mit allen relevanten Ziffern ausdrucken.
Ich habe dieses Problem gelöst, indem ich Folgendes geändert habe:
someNumber = someNumber.toFixed(2)
... dazu:
someNumber = +someNumber.toFixed(2);
Dadurch wird die Zahl jedoch in eine Zeichenfolge konvertiert und erneut analysiert, was sich erheblich auf die Leistung auswirkt. Wenn Sie Wert auf Leistung oder Typensicherheit legen, überprüfen Sie auch die anderen Antworten.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Siehe meine Antwort für einen allgemeineren Weg.
Warum nicht verwenden parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Natürlich gibt es einen String zurück. Wenn Sie die numerische Variable runden möchten, verwenden Sie stattdessen Math.round (). Der Punkt von toFixed besteht darin, die Zahl mit einer festen Anzahl von Dezimalstellen zu formatieren, die dem Benutzer angezeigt werden sollen .
Was würden Sie erwarten, wenn es eine Zahl formatieren soll? Wenn Sie eine Nummer haben, können Sie so ziemlich nichts damit anfangen, weil zB 2 == 2.0 == 2.00
usw., also muss es eine Zeichenfolge sein.
Um ein Beispiel dafür zu liefern, warum es sich um eine Zeichenfolge handeln muss:
Wenn Sie 1.toFixed (2) formatieren, erhalten Sie '1.00'.
Dies ist nicht dasselbe wie 1, da 1 keine 2 Dezimalstellen hat.
Ich weiß, dass JavaScript nicht gerade eine Leistungssprache ist, aber es besteht die Möglichkeit, dass Sie eine bessere Leistung für eine Rundung erzielen, wenn Sie Folgendes verwenden: roundValue = Math.round (Wert * 100) * 0,01
Weil es hauptsächlich darum geht, Zahlen anzuzeigen? Wenn Sie Zahlen runden möchten, verwenden Sie diese Math.round()
mit geeigneten Faktoren.
'42'
eine Zahl ist ... was es nicht ist. Nur weil eine Zeichenfolge nur Ziffern enthält, wird sie nicht zu einer Zahl. Dies ist kein PHP. :-P
Hier ist eine etwas funktionalere Version der Antwort m93a
.
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12