Wie formatiere ich einen Float in Javascript?

427

Wie kann ich in JavaScript beim Konvertieren von einem Float in einen String nur zwei Stellen nach dem Dezimalpunkt erhalten? Zum Beispiel 0,34 anstelle von 0,3445434.

jww
quelle
16
Nur ein bisschen Nit-Picking: Möchten Sie alle bis auf die beiden ersten Ziffern abhacken oder auf zwei Ziffern runden?
xtofl

Antworten:

232
var result = Math.round(original*100)/100;

Die Einzelheiten , falls der Code nicht selbsterklärend ist.

edit: ... oder einfach benutzen toFixed, wie von Tim Büthe vorgeschlagen . Ich habe das vergessen, danke (und eine positive Bewertung) für die Erinnerung :)

kkyy
quelle
1
Ich habe dies in der Bibliothek "Highchart" verwendet, wo es keine Zeichenfolgenwerte akzeptiert, daher hat toFixed bei mir nicht funktioniert. Math.round hat mein Problem gelöst, danke
Swapnil Chincholkar
4
toFixed()ahmt nach, was so etwas printf()in C macht, toFixed()und Math.round()behandelt das Runden anders. In diesem Fall hat toFixed()dies den gleichen Effekt Math.floor()(vorausgesetzt, Sie multiplizieren das Original vorher mit 10 ^ n und rufen toFixed()mit n Ziffern auf). Die "Richtigkeit" der Antwort hängt sehr davon ab, was das OP hier will, und beide sind auf ihre Weise "richtig".
DDPWNAGE
838

Es gibt Funktionen zum Runden von Zahlen. Zum Beispiel:

var x = 5.0364342423;
print(x.toFixed(2));

druckt 5.04.

EDIT: Geige

Tim Büthe
quelle
7
Ich würde jedoch empfehlen, print () nicht in einem Browser zu verwenden
cobbal
70
Seien Sie vorsichtig, toFixed () gibt einen String zurück: var x = 5.036432346; var y = x.toFixed(2) + 100; ywird gleich sein"5.03100"
Vlad
5
Beachten Sie, dass (1e100) .toFixed (2) === "1e + 100"
qbolec
7
(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
Achten Sie auch auf
3
Wenn Sie nach einem Äquivalent zu toFixed suchen, jedoch mit konsistenter Rundung, verwenden Sie toLocaleString: (0.345) .toLocaleString ('en-EN', {minimalFractionDigits: 2, maximumFractionDigits: 2})
fred727
185

Seien Sie vorsichtig bei der Verwendung von toFixed():

Zunächst wird die Zahl mit der binären Darstellung der Zahl gerundet, was zu unerwartetem Verhalten führen kann. Zum Beispiel

(0.595).toFixed(2) === '0.59'

statt '0.6'.

Zweitens gibt es einen IE-Fehler mit toFixed(). Im IE (zumindest bis Version 7, IE8 wurde nicht überprüft) gilt Folgendes:

(0.9).toFixed(0) === '0'

Es könnte eine gute Idee sein, dem Vorschlag von kkyy zu folgen oder eine benutzerdefinierte toFixed()Funktion zu verwenden, z

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}
Christoph
quelle
Ja, dies kann sehr wichtig sein, wenn Code zur Vorhersage von Preisen erstellt wird. Vielen Dank! +1
Fabio Milheiro
10
Ich würde vorschlagen, die native .toFixed()Methode zum Rückgabewert hinzuzufügen, wodurch die erforderliche Genauigkeit hinzugefügt wird, z. B.: return (Math.round(value * power) / power).toFixed(precision);Und der Wert auch als Zeichenfolge zurückgegeben wird. Andernfalls wird eine Genauigkeit von 20 für kleinere Dezimalstellen ignoriert
William Joss Crowcroft
3
Ein Hinweis zu toFixed: Beachten Sie, dass das Erhöhen der Genauigkeit zu unerwarteten Ergebnissen führen kann : (1.2).toFixed(16) === "1.2000000000000000", während (1.2).toFixed(17) === "1.19999999999999996"(in Firefox / Chrome; in IE8 gilt letzteres aufgrund der geringeren Genauigkeit, die IE8 intern bieten kann, nicht).
Jakub.g
2
Bitte beachten Sie, dass auch (0.598).toFixed(2)nicht produziert 0.6. Es produziert 0.60:)
qbolec
1
Achten Sie auch auf inkonsistente Rundungen : (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
Skippy le Grand Gourou
36

Ein weiteres zu beachtendes Problem besteht darin, dass toFixed()am Ende der Zahl unnötige Nullen erzeugt werden können. Zum Beispiel:

var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"

Die Idee ist, die Ausgabe mit einem zu bereinigen RegExp:

function humanize(x){
  return x.toFixed(6).replace(/\.?0*$/,'');
}

Das RegExpentspricht den nachgestellten Nullen (und optional dem Dezimalpunkt), um sicherzustellen, dass es auch für Ganzzahlen gut aussieht.

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"
qbolec
quelle
Number.prototype.minFixed = Funktion (Dezimalstellen) {return this.toFixed (Dezimalstellen) .replace (/ \.? 0 * $ /, ""); }
Luc Bloom
Dies sollte akzeptiert werden, nachgestellte Nullen sind ärgerlich, ich habe genau nach dieser Lösung gesucht, gj.
Exoslav
1
Nachgestellte Nullen mögen ärgerlich sein, aber genau das verspricht der Methodenname "toFixed" zu tun;)
ksadowski
11
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding
Ilya Birman
quelle
Math.round (1.015 * 100) / 100 ergibt 1.01, während wir erwarten würden, dass es 1.02 ist?
Gaurav5430
6

Es gibt ein Problem mit all diesen Lösungen, die mit Multiplikatoren herumschwirren. Die Lösungen von kkyy und Christoph sind leider falsch.

Bitte testen Sie Ihren Code für die Nummer 551.175 mit 2 Dezimalstellen - er wird auf 551.17 gerundet, während er 551.18 sein sollte ! Aber wenn Sie zum Beispiel testen. 451.175 wird es in Ordnung sein - 451.18. Daher ist es schwierig, diesen Fehler auf den ersten Blick zu erkennen.

Das Problem liegt in der Multiplikation: Versuchen Sie es mit 551.175 * 100 = 55117.49999999999 (ups!)

Meine Idee ist es also, es mit toFixed () zu behandeln, bevor ich Math.round () verwende.

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}
ArteQ
quelle
1
Das ist das Problem mit der Arithmetik in js: (551.175 * 10 * 10)! == (551.175 * 100). Sie müssen Dezimalinkremente verwenden, um das Komma für nicht echte Dezimalergebnisse zu verschieben.
Kir Kanos
+1, um dies zu bemerken toFixed betroffen - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)… Welche Methode auch immer verwendet wird, fügen Sie vor der Rundung besser ein Epsilon hinzu.
Skippy le Grand Gourou
5

Der Schlüssel hier ist wohl, zuerst richtig aufzurunden, dann können Sie ihn in String konvertieren.

function roundOf(n, p) {
    const n1 = n * Math.pow(10, p + 1);
    const n2 = Math.floor(n1 / 10);
    if (n1 >= (n2 * 10 + 5)) {
        return (n2 + 1) / Math.pow(10, p);
    }
    return n2 / Math.pow(10, p);
}

// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34

Jetzt können Sie diesen Wert sicher mit toFixed (p) formatieren. Also mit Ihrem speziellen Fall:

roundOf(0.3445434, 2).toFixed(2); // 0.34
Steven
quelle
3

Wenn Sie die Zeichenfolge ohne Runde möchten, können Sie diese RegEx verwenden (vielleicht ist dies nicht der effizienteste Weg ... aber es ist wirklich einfach).

(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'
Pablo Andres Diaz Mazzaro
quelle
1
function trimNumber(num, len) {
  const modulu_one = 1;
  const start_numbers_float=2;
  var int_part = Math.trunc(num);
  var float_part = String(num % modulu_one);
      float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
  return int_part+'.'+float_part;
}
ofir_aghai
quelle
Gute Antwort, außer dass Ihnen Semikolons fehlen (Nein, in es6 sind Semikolons nicht veraltet und wir müssen sie in einigen Fällen noch verwenden). Ich musste auch bearbeiten letzte Reihe: return float_part ? int_part+'.'+float_part : int_part;sonst , wenn Sie Integer übergeben, es zurück Zahl mit einem Punkt am Ende (zB Eingang: 2100, Ausgang: 2100.)
Kuba Šimonovský
0

Vielleicht möchten Sie auch ein Dezimaltrennzeichen? Hier ist eine Funktion, die ich gerade gemacht habe:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}
Rodrigo
quelle
0

Es gibt keine Möglichkeit, eine inkonsistente Rundung von Preisen mit x.xx5 als tatsächlichem Wert durch Multiplikation oder Division zu vermeiden. Wenn Sie auf Kundenseite die richtigen Preise berechnen müssen, sollten Sie alle Beträge in Cent aufbewahren. Dies liegt an der Art der internen Darstellung numerischer Werte in JavaScript. Beachten Sie, dass Excel unter denselben Problemen leidet, sodass die meisten Benutzer die kleinen Fehler, die durch dieses Phänomen verursacht werden, nicht bemerken würden. Obwohl sich Fehler ansammeln können, wenn Sie viele berechnete Werte addieren, gibt es eine ganze Theorie, die die Reihenfolge der Berechnungen und andere Methoden zur Minimierung des Fehlers im Endergebnis beinhaltet. Um die Probleme mit Dezimalwerten hervorzuheben, beachten Sie bitte, dass 0,1 + 0,2 in JavaScript nicht genau gleich 0,3 ist, während 1 + 2 gleich 3 ist.

Dony
quelle
Die Lösung wäre, den gesamten Teil und den Dezimalteil zu trennen und sie als ganze Zahlen in Basis 10 darzustellen, anstatt Gleitkommazahlen zu verwenden. Hier funktioniert es problemlos für PrettyPrint, aber im Allgemeinen müssen Sie zwischen einer Basis und einer anderen wählen, eine Darstellung für reelle Zahlen und eine andere, jede hat ihre Probleme
läuft
"Excel leidet unter den gleichen Problemen". Quelle ?
Gaurav5430
0
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) { 
    if (!nbDec) nbDec = 100;
    var a = Math.abs(x);
    var e = Math.floor(a);
    var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
    var signStr = (x<0) ? "-" : " ";
    var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
    var eStr = e.toString();
    return signStr+eStr+"."+decStr;
}

prettyFloat(0);      //  "0.00"
prettyFloat(-1);     // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5);    //  "0.50"
reuns
quelle
0

Ich benutze diesen Code, um Floats zu formatieren. Es basiert auf, entfernt toPrecision()aber unnötige Nullen. Ich würde Vorschläge zur Vereinfachung der Regex begrüßen.

function round(x, n) {
    var exp = Math.pow(10, n);
    return Math.floor(x*exp + 0.5)/exp;
}

Anwendungsbeispiel:

function test(x, n, d) {
    var rounded = rnd(x, d);
    var result = rounded.toPrecision(n);
    result = result.replace(/\.?0*$/, '');
    result = result.replace(/\.?0*e/, 'e');
    result = result.replace('e+', 'e');
    return result;  
}

document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
Kennzeichen
quelle