Question Comment imprimer un nombre avec des virgules comme séparateurs de milliers dans JavaScript


J'essaie d'imprimer un entier dans JavaScript avec des virgules comme séparateurs de milliers. Par exemple, je souhaite afficher le numéro 1234567 en tant que "1 234 567". Comment ferais-je cela?

Voici comment je le fais:

function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

Y a-t-il une façon plus simple ou plus élégante de le faire? Ce serait bien si cela fonctionne aussi avec des flotteurs, mais ce n'est pas nécessaire. Il n'a pas besoin d'être spécifique aux paramètres régionaux pour choisir entre les points et les virgules.


1165
2018-05-24 23:42


origine


Réponses:


J'ai utilisé l'idée de la réponse de Kerry, mais je l'ai simplifiée puisque je cherchais simplement quelque chose de simple dans mon but spécifique. Voici ce que j'ai fait:

const numberWithCommas = (x) => {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

C'est tout ce que vous avez vraiment besoin de savoir.

@Neils Bom a demandé comment fonctionne la regex. Mon explication est longue. Cela ne rentre pas dans les commentaires et je ne sais pas où le mettre autrement, alors je le fais ici. Si quelqu'un a d'autres suggestions pour savoir où le mettre, s'il vous plaît faites le moi savoir.

La regex utilise 2 assertions lookahead: une positive pour rechercher un point dans la chaîne qui a un multiple de 3 chiffres dans une ligne après elle, et une assertion négative pour s'assurer que ce point a seulement un multiple de 3 chiffres. L'expression de remplacement met une virgule là.

Par exemple, si vous le passez "123456789.01", l'assertion positive correspondra à chaque point à gauche du 7 (puisque "789" est un multiple de 3 chiffres, "678" est un multiple de 3 chiffres, "567", etc.). L'assertion négative vérifie que le multiple de 3 chiffres n'a pas de chiffres après lui. "789" a une période après celle-ci donc c'est exactement un multiple de 3 chiffres, donc une virgule y va. "678" est un multiple de 3 chiffres mais il a un "9" après, donc ces 3 chiffres font partie d'un groupe de 4, et une virgule ne va pas là. De même pour "567". "456789" a 6 chiffres, ce qui est un multiple de 3, donc une virgule va avant. "345678" est un multiple de 3, mais il a un "9" après, donc pas de virgule. Etc. Le "\ B" empêche l'expression régulière de mettre une virgule au début de la chaîne.

@ neu-rah a mentionné que cette fonction ajoute des virgules dans des endroits indésirables s'il y a plus de 3 chiffres après la virgule décimale. Si c'est un problème, vous pouvez utiliser cette fonction:

const numberWithCommas = (x) => {
  var parts = x.toString().split(".");
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return parts.join(".");
}

2061
2018-05-25 00:40



Je suis surpris personne n'a mentionné Number.prototype.toLocaleString. Il est implémenté dans JavaScript 1.5 (qui a été introduit en 1999), il est donc essentiellement supporté par les principaux navigateurs.

var n = 34523453.345
n.toLocaleString()
"34,523,453.345"

Il fonctionne également dans Node.js à partir de la version v0.12 via l'inclusion de Intl

Si vous voulez quelque chose de différent, Numeral.js pourrait être intéressant.


1046
2017-07-15 21:01



var number = 1234567890; // Example number to be converted

 Rappelez-vous que javascript a un entier maximum valeur de 9007199254740991


toLocaleString:

number.toLocaleString(); // "1,234,567,890"

// A more complex example: 
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"


Format de nombre (Safari non supporté):

var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"

De ce que j'ai vérifié (Firefox au moins), ils sont plus ou moins la même chose en ce qui concerne les performances.


177
2017-08-22 08:52



Je suggère d'utiliser phpjs.org's Format de nombre()

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

MISE À JOUR 13/02/14

Les gens ont signalé que cela ne fonctionne pas comme prévu, alors j'ai fait un JS Fiddle Cela inclut des tests automatisés.

Mise à jour 26/11/2017

Voici ce violon comme un extrait de pile avec une sortie légèrement modifiée:

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

var exampleNumber = 1;
function test(expected, number, decimals, dec_point, thousands_sep)
{
    var actual = number_format(number, decimals, dec_point, thousands_sep);
    console.log(
        'Test case ' + exampleNumber + ': ' +
        '(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) +
        ', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' +
        ', thousands_sep: "' + (typeof thousands_sep === 'undefined' ? '(default)' : thousands_sep) + '")'
    );
    console.log('  => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", expected "' + expected + '".');
    exampleNumber++;
}

test('1,235',    1234.56);
test('1 234,56', 1234.56, 2, ',', ' ');
test('1234.57',  1234.5678, 2, '.', '');
test('67,00',    67, 2, ',', '.');
test('1,000',    1000);
test('67.31',    67.311, 2);
test('1,000.6',  1000.55, 1);
test('67.000,00000', 67000, 5, ',', '.');
test('1',        0.9, 0);
test('1.20',     '1.20', 2);
test('1.2000',   '1.20', 4);
test('1.200',    '1.2000', 3);
.as-console-wrapper {
  max-height: 100% !important;
}


86
2018-05-24 23:47



Ceci est une variation de la réponse de @ mikez302, mais modifiée pour prendre en charge les nombres avec des nombres décimaux (les commentaires de @ neu-rah indiquent que numberWithCommas (12345.6789) -> "12,345.6,789" au lieu de "12,345.6789"

function numberWithCommas(n) {
    var parts=n.toString().split(".");
    return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}

65
2018-06-05 15:03



function formatNumber (num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
}

print(formatNumber(2665));      // 2,665
print(formatNumber(102665));    // 102,665
print(formatNumber(111102665)); // 111,102,665

54
2017-08-19 06:47



Merci à tous pour leurs réponses. J'ai développé certaines des réponses pour faire une solution plus "one-size-fits-all".

Le premier extrait ajoute une fonction qui imite PHPde number_format() au prototype de nombre. Si je suis en train de formater un nombre, je veux généralement des décimales afin que la fonction prenne en compte le nombre de décimales à afficher. Certains pays utilisent des virgules comme décimales et décimales comme séparateur de milliers, de sorte que la fonction permet de définir ces séparateurs.

Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.toFixed(decimals).split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);

    return parts.join(dec_point);
}

Vous utiliserez ceci comme suit:

var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

J'ai trouvé que j'avais souvent besoin de récupérer le nombre pour les opérations mathématiques, mais parseFloat convertit 5000 à 5, en prenant simplement la première séquence de valeurs entières. J'ai donc créé ma propre fonction de conversion flottante et l'ai ajoutée au prototype String.

String.prototype.getFloat = function(dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.split(dec_point);
    var re = new RegExp("[" + thousands_sep + "]");
    parts[0] = parts[0].replace(re, '');

    return parseFloat(parts.join(dec_point));
}

Vous pouvez maintenant utiliser les deux fonctions comme suit:

var foo = 5000;
var fooString = foo.numberFormat(2); // The string 5,000.00
var fooFloat = fooString.getFloat(); // The number 5000;

console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00

31
2017-09-18 01:50