web-dev-qa-db-fra.com

Comment formater un float en javascript?

En JavaScript, lors de la conversion d'un float en chaîne, comment puis-je obtenir 2 chiffres après le point décimal? Par exemple, 0,34 au lieu de 0,3445434.

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

Les détails , au cas où le code ne serait pas explicite.

edit: ... ou utilisez simplement toFixed, comme proposé par Tim Büthe . Oublié celui-là, merci (et un upvote) pour rappel :)

221
kkyy

Il y a des fonctions pour arrondir les nombres. Par exemple:

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

imprimera 5.04.

EDIT: Violon

791
Tim Büthe

Soyez prudent lorsque vous utilisez toFixed():

Tout d'abord, arrondir le nombre est effectué à l'aide de la représentation binaire du nombre, ce qui peut entraîner un comportement inattendu. Par exemple

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

au lieu de '0.6'.

Deuxièmement, il y a un bogue IE avec toFixed(). Dans IE (du moins jusqu'à la version 7, ne vérifie pas IE8), ce qui suit est vrai:

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

Cela peut être une bonne idée de suivre la suggestion de kkyy ou d’utiliser une fonction personnalisée toFixed(), par exemple

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}
180
Christoph

Un autre problème à prendre en compte est que toFixed() peut produire des zéros inutiles à la fin du nombre. Par exemple:

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

L'idée est de nettoyer la sortie en utilisant un RegExp:

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

Le RegExp correspond aux zéros de fin (et éventuellement au point décimal) pour s’assurer qu’il convient également aux entiers.

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"
32
qbolec
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make Nice rounding
10
Ilya Birman

Il y a un problème avec toutes ces solutions flottant autour de multiplicateurs. Les solutions de Kkyy et de Christoph sont malheureusement mauvaises.

Veuillez tester votre code pour le nombre 551.175 avec 2 décimales - il sera arrondi à 551.17 alors qu'il devrait l'être 551.18! Mais si vous testez pour ex. 451.175 ça ira - 451.18. Il est donc difficile de repérer cette erreur au premier abord.

Le problème est avec la multiplication: essayez 551.175 * 100 = 55117.49999999999 (ups!)

Donc, mon idée est de le traiter avec toFixed () avant d'utiliser Math.round ();

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}
6
ArteQ

La clé ici, je suppose, est d’arrondir correctement d’abord, puis vous pouvez le convertir en chaîne.

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

Vous pouvez maintenant formater cette valeur en toute sécurité avec toFixed (p). Donc, avec votre cas spécifique:

roundOf(0.3445434, 2).toFixed(2); // 0.34
3
Steven
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;
}
1
ofir_aghai

Il n'y a aucun moyen d'éviter des arrondis incohérents pour les prix avec x.xx5 comme valeur réelle en utilisant la multiplication ou la division. Si vous devez calculer des prix corrects côté client, vous devez conserver tous les montants en cents. Cela est dû à la nature de la représentation interne des valeurs numériques en JavaScript. Notez que Excel souffre des mêmes problèmes et que la plupart des gens ne remarquent pas les petites erreurs causées par ce phénomène. Si les erreurs peuvent s'accumuler chaque fois que vous additionnez un grand nombre de valeurs calculées, il existe toute une théorie autour de cela impliquant l'ordre des calculs et d'autres méthodes permettant de minimiser l'erreur dans le résultat final. Pour souligner les problèmes liés aux valeurs décimales, veuillez noter que 0,1 + 0,2 n’est pas exactement égal à 0,3 en JavaScript, tandis que 1 + 2 est égal à 3.

0
Dony

Si vous voulez une corde sans rond, vous pouvez utiliser ce RegEx (peut-être que ce n'est pas le moyen le plus efficace ... mais c'est vraiment facile)

(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'

Peut-être voudrez-vous aussi un séparateur décimal? Voici une fonction que je viens de créer:

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;
}
0
Rodrigo

J'utilise ce code pour formater les floats. Il est basé sur toPrecision() mais il supprime les zéros inutiles. Je serais heureux de recevoir des suggestions sur la façon de simplifier la regex.

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

Exemple d'utilisation:

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>');
0
Mark
/** 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"
0
reuns