web-dev-qa-db-fra.com

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

J'essaie d'imprimer un entier dans JavaScript avec des virgules comme séparateur de milliers. Par exemple, je veux afficher le nombre 1234567 sous la forme "1 234 567". Comment pourrais-je m'y prendre?

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 un moyen plus simple ou plus élégant de le faire? Ce serait bien si cela fonctionnait aussi avec des flotteurs, mais ce n'est pas nécessaire. Il n’est pas nécessaire que ce soit spécifique aux paramètres régionaux pour choisir entre des points et des virgules.

1507
Elias Zamaria

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

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

C'est tout ce que vous devez vraiment savoir.

@Neils Bom a demandé comment fonctionne la regex. Mon explication est un peu longue. Cela ne rentre pas dans les commentaires et je ne sais pas où le dire, je le fais ici. Si quelqu'un a d'autres suggestions pour savoir où le mettre, merci de me le faire savoir.

La regex utilise 2 assertions lookahead: une positive pour rechercher n'importe quel point de la chaîne précédé d'un multiple de 3 chiffres, et une assertion négative pour s'assurer que ce point ne contient qu'un multiple de 3 chiffres exactement. L'expression de remplacement met une virgule ici.

Par exemple, si vous passez "123456789.01", l'assertion positive correspondra à chaque position à 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 ne comporte aucun chiffre après celui-ci. "789" est suivi d'un point, il s'agit donc d'un multiple de 3 chiffres. Une virgule y figure. "678" est un multiple de 3 chiffres mais il est suivi d'un "9". Ces 3 chiffres font donc partie d'un groupe de 4 et aucune virgule n'y figure. De même pour "567". "456789" est composé de 6 chiffres, ce qui est un multiple de 3, donc une virgule va avant. "345678" est un multiple de 3, mais il comporte un "9" à la suite, aucune virgule n'y apparaît. Etc. Le "\ B" empêche la regex de mettre une virgule au début de la chaîne.

@ neu-rah mentionne que cette fonction ajoute des virgules aux endroits indésirables s'il y a plus de 3 chiffres après le point décimal. Si cela pose un problème, vous pouvez utiliser cette fonction:

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

Je suis surpris que personne n'ait mentionné Number.prototype.toLocaleString . Implémenté dans JavaScript 1.5 (introduit en 1999), il est essentiellement pris en charge par tous les principaux navigateurs.

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

Cela fonctionne aussi dans Node.js à partir de v0.12 en incluant Intl

Faites juste attention que cette fonction retourne une chaîne, pas un nombre.

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

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

⚠ Remarquez que javascript a une valeur entier maximal 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"


NumberFormat ( Safari non pris en charge):

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

D'après ce que j'ai vérifié (au moins Firefox), ils sont plus ou moins identiques en ce qui concerne les performances.

213
vsync

Je suggère d'utiliser les phpjs.org number_format ()

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);
}

UPDATE 02/13/14

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

Mise à jour du 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;
}
100
Kerry Jones

Ceci est une variante 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 ce nombreAvecCommas (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] : "");
}
68
user1437663
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
62
Tutankhamen

Utilisation de l'expression régulière

function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(toCommas(123456789)); // 123,456,789

console.log(toCommas(1234567890)); // 1,234,567,890
console.log(toCommas(1234)); // 1,234

Utilisation de toLocaleString ()

var number = 123456.789;

// request a currency format
console.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));
// → 123.456,79 €

// the Japanese yen doesn't use a minor unit
console.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))
// → ¥123,457

// limit to three significant digits
console.log(number.toLocaleString('en-IN', { maximumSignificantDigits: 3 }));
// → 1,23,000

ref MDN: Number.prototype.toLocaleString ()

Utilisation de Intl.NumberFormat ()

var number = 123456.789;

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
// expected output: "123.456,79 €"

// the Japanese yen doesn't use a minor unit
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
// expected output: "¥123,457"

// limit to three significant digits
console.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));

// expected output: "1,23,000"

ref Intl.NumberFormat

DEMO AT ICI

<script type="text/javascript">
  // Using Regular expression
  function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  }

  function commas() {
    var num1 = document.myform.number1.value;

    // Using Regular expression
    document.getElementById('result1').value = toCommas(parseInt(num1));
    // Using toLocaleString()

    document.getElementById('result2').value = parseInt(num1).toLocaleString('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    });

    // Using Intl.NumberFormat()
    document.getElementById('result3').value = new Intl.NumberFormat('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    }).format(num1);
  }
</script>
<FORM NAME="myform">
  <INPUT TYPE="text" NAME="number1" VALUE="123456789">
  <br>
  <INPUT TYPE="button" NAME="button" Value="=>" onClick="commas()">
  <br>Using Regular expression
  <br>
  <INPUT TYPE="text" ID="result1" NAME="result1" VALUE="">
  <br>Using toLocaleString()
  <br>
  <INPUT TYPE="text" ID="result2" NAME="result2" VALUE="">
  <br>Using Intl.NumberFormat()
  <br>
  <INPUT TYPE="text" ID="result3" NAME="result3" VALUE="">

</FORM>

Performance

Performancehttp://jsben.ch/sifRd

47
Tính Ngô Quang

Intl.NumberFormat

Fonction JS native. Pris en charge par IE11, Edge, les dernières versions de Safari, Chrome, Firefox, Opera, Safari sur iOS et Chrome sur Android.

var number = 3500;

console.log(new Intl.NumberFormat().format(number));
// → '3,500' if in US English locale
36
Dustin Sun

Merci à tous pour leurs réponses. Je me suis inspiré de certaines des réponses pour créer une solution plus universelle.

Le premier extrait ajoute une fonction qui imite LA FONCTION number_format() DE _ _ _ _ _ _ _ _ _ _ au prototype Number. Si je formate un nombre, je veux généralement des décimales afin que la fonction prenne le nombre de décimales à afficher. Certains pays utilisent des virgules comme décimales et des décimales comme séparateurs des milliers afin que la fonction permette 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 utiliseriez 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 constaté que j'avais souvent besoin de récupérer le nombre pour les opérations mathématiques, mais parseFloat convertit 5 000 en 5, en prenant simplement la première séquence de valeurs entières. J'ai donc créé ma propre fonction de conversion float et l'a 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));
}

Maintenant, vous pouvez 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
32
J.Money

Je pense que c'est l'expression régulière la plus courte qui le fait:

/\B(?=(\d{3})+\b)/g

"123456".replace(/\B(?=(\d{3})+\b)/g, ",")

Je l'ai vérifié sur quelques chiffres et cela a fonctionné.

21
user3664916

Number.prototype.toLocaleString() aurait été génial s'il avait été fourni nativement par tous les navigateurs (Safari).

J'ai vérifié toutes les autres réponses, mais personne ne semblait vouloir le remplir. Voici un point positif vers cela, qui est en réalité une combinaison des deux premières réponses; si toLocaleString fonctionne, il l'utilise, sinon il utilise une fonction personnalisée.

var putThousandsSeparators;

putThousandsSeparators = function(value, sep) {
  if (sep == null) {
    sep = ',';
  }
  // check if it needs formatting
  if (value.toString() === value.toLocaleString()) {
    // split decimals
    var parts = value.toString().split('.')
    // format whole numbers
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
    // put them back together
    value = parts[1] ? parts.join('.') : parts[0];
  } else {
    value = value.toLocaleString();
  }
  return value;
};

alert(putThousandsSeparators(1234567.890));
18
Sinan

Le séparateur de milliers peut être inséré de manière conviviale à l'échelle internationale à l'aide de l'objet Intl du navigateur:

Intl.NumberFormat().format(1234);
// returns "1,234" if the user's locale is en_US, for example

Voir article de MDN sur NumberFormat pour plus d'informations, vous pouvez spécifier le comportement des paramètres régionaux ou le comportement par défaut de l'utilisateur. C'est un peu plus infaillible car il respecte les différences locales; de nombreux pays utilisent des points pour séparer les chiffres, tandis qu'une virgule indique les décimales.

Intl.NumberFormat n'est pas encore disponible dans tous les navigateurs, mais il fonctionne dans les dernières versions de Chrome, Opera et IE. La prochaine version de Firefox devrait le supporter. Webkit ne semble pas avoir de calendrier pour la mise en œuvre.

16
phette23

Vous pouvez soit utiliser cette procédure pour formater votre devise nécessaire.

var nf = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’

Pour plus d'informations, vous pouvez accéder à ce lien.

https://www.justinmccandless.com/post/formatting-currency-in-javascript/

15
Dulith De Costa

si vous traitez beaucoup avec des valeurs monétaires et un formatage important, il peut être intéressant d’ajouter minuscule accounting.js qui gère un grand nombre de cas Edge et de localisation:

// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00

// European formatting (custom symbol and separators), could also use options object as second param:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99

// Negative values are formatted nicely, too:
accounting.formatMoney(-500000, "£ ", 0); // £ -500,000

// Simple `format` string allows control of symbol position [%v = value, %s = symbol]:
accounting.formatMoney(5318008, { symbol: "GBP",  format: "%v %s" }); // 5,318,008.00 GBP
13
Shital Shah

Le code suivant utilise char scan, il n'y a donc pas de regex.

function commafy( num){
  var parts = (''+(num<0?-num:num)).split("."), s=parts[0], L, i=L= s.length, o='';
  while(i--){ o = (i===0?'':((L-i)%3?'':',')) 
                  +s.charAt(i) +o }
  return (num<0?'-':'') + o + (parts[1] ? '.' + parts[1] : ''); 
}

Il montre des performances prometteuses: http://jsperf.com/number-formatting-with-commas/5

2015.4.26: Correctif mineur permettant de résoudre le problème lorsque num <0. Voir https://jsfiddle.net/runsun/p5tqqvs3/

12
runsun

Voici une fonction simple qui insère des virgules pour mille séparateurs. Il utilise des fonctions de tableau plutôt qu'un RegEx.

/**
 * Format a number as a string with commas separating the thousands.
 * @param num - The number to be formatted (e.g. 10000)
 * @return A string representing the formatted number (e.g. "10,000")
 */
var formatNumber = function(num) {
    var array = num.toString().split('');
    var index = -3;
    while (array.length + index > 0) {
        array.splice(index, 0, ',');
        // Decrement by 4 since we just added another unit to the array.
        index -= 4;
    }
    return array.join('');
};

Lien CodeSandbox avec des exemples: https://codesandbox.io/s/p38k63w0vq

11
Noah Freitas

Utilisez ce code pour gérer le format monétaire pour l'Inde. Le code de pays peut être modifié pour gérer la devise d'un autre pays.

let amount =350256.95
var formatter = new Intl.NumberFormat('en-IN', {
  minimumFractionDigits: 2,
});

// Use it.

formatter.format(amount);

sortie:

3,50,256.95
9
Bathri Nathan

J'ai écrit celui-ci avant de trébucher sur ce post. Pas de regex et vous pouvez réellement comprendre le code.

$(function(){
  
  function insertCommas(s) {

    // get stuff before the dot
    var d = s.indexOf('.');
    var s2 = d === -1 ? s : s.slice(0, d);

    // insert commas every 3 digits from the right
    for (var i = s2.length - 3; i > 0; i -= 3)
      s2 = s2.slice(0, i) + ',' + s2.slice(i);

    // append fractional part
    if (d !== -1)
      s2 += s.slice(d);

    return s2;

  }
  
  
  $('#theDudeAbides').text( insertCommas('1234567.89012' ) );
  
  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="theDudeAbides"></div>
7
Ronnie Overby

Pour moi, la meilleure réponse consiste à utiliser toLocaleString, comme l'ont dit certains membres. Si vous souhaitez inclure le symbole '$', ajoutez simplement des options de langue et de type. Voici un exemple pour formater un nombre en pesos mexicains

var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))

raccourci

1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})
6
Carlos A. Ortiz

Vous pouvez également utiliser le constructeur Intl.NumberFormat . Voici comment vous pouvez le faire.

 resultNumber = new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(yourNumber); 
5
Oliver
var formatNumber = function (number) {
  var splitNum;
  number = Math.abs(number);
  number = number.toFixed(2);
  splitNum = number.split('.');
  splitNum[0] = splitNum[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return splitNum.join(".");
}

EDIT: La fonction ne fonctionne qu'avec un nombre positif. pour exemple:

var number = -123123231232;
formatNumber(number)

Sortie: "123,123,231,232"

Mais pour répondre à la question ci-dessus, la méthode toLocaleString() résout simplement le problème.

var number = 123123231232;
    number.toLocaleString()

Sortie: "123,123,231,232"

Acclamation!

5
Kiry Meas

Laissez-moi essayer d'améliorer Kolkaréponse et peut-être aider les autres à gagner du temps.

Utilisez Numeral.js .

document.body.textContent = numeral(1234567).format('0,0');
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>

Vous devriez aller avec Number.prototype.toLocaleString () seulement si sa compatibilité du navigateur n'est pas un problème.

5
Beder Acosta Borges

Je pense que cette fonction prendra en charge toutes les questions liées à ce problème.

function commaFormat(inputString) {
    inputString = inputString.toString();
    var decimalPart = "";
    if (inputString.indexOf('.') != -1) {
        //alert("decimal number");
        inputString = inputString.split(".");
        decimalPart = "." + inputString[1];
        inputString = inputString[0];
        //alert(inputString);
        //alert(decimalPart);

    }
    var outputString = "";
    var count = 0;
    for (var i = inputString.length - 1; i >= 0 && inputString.charAt(i) != '-'; i--) {
        //alert("inside for" + inputString.charAt(i) + "and count=" + count + " and outputString=" + outputString);
        if (count == 3) {
            outputString += ",";
            count = 0;
        }
        outputString += inputString.charAt(i);
        count++;
    }
    if (inputString.charAt(0) == '-') {
        outputString += "-";
    }
    //alert(outputString);
    //alert(outputString.split("").reverse().join(""));
    return outputString.split("").reverse().join("") + decimalPart;
}
4
AbhinavRanjan

Une manière alternative, en soutenant des nombres décimaux, des séparateurs et des négatifs différents.

var number_format = function(number, decimal_pos, decimal_sep, thousand_sep) {
    var ts      = ( thousand_sep == null ? ',' : thousand_sep )
        , ds    = ( decimal_sep  == null ? '.' : decimal_sep )
        , dp    = ( decimal_pos  == null ? 2   : decimal_pos )

        , n     = Math.abs(Math.floor(number)).toString()

        , i     = n.length % 3 
        , f     = ((number < 0) ? '-' : '') + n.substr(0, i)
    ;

    for(;i<n.length;i+=3) {
        if(i!=0) f+=ts;
        f+=n.substr(i,3);
    }

    if(dp > 0) 
        f += ds + parseFloat(number).toFixed(dp).split('.')[1]

    return f;
}

Quelques corrections de @Jignesh Sanghani, n'oubliez pas de revenir sur son commentaire.

3
Felipe Buccioni

J'ai ajouté tofixed à la solution de Aki143S. Cette solution utilise des points pour des milliers de séparateurs et une virgule pour la précision.

function formatNumber( num, fixed ) { 
    var decimalPart;

    var array = Math.floor(num).toString().split('');
    var index = -3; 
    while ( array.length + index > 0 ) { 
        array.splice( index, 0, '.' );              
        index -= 4;
    }

    if(fixed > 0){
        decimalPart = num.toFixed(fixed).split(".")[1];
        return array.join('') + "," + decimalPart; 
    }
    return array.join(''); 
};

Exemples;

formatNumber(17347, 0)  = 17.347
formatNumber(17347, 3)  = 17.347,000
formatNumber(1234563.4545, 3)  = 1.234.563,454
3
bartburkhardt

Beaucoup de bonnes réponses déjà. En voici un autre, juste pour le plaisir:

function format(num, fix) {
    var p = num.toFixed(fix).split(".");
    return p[0].split("").reduceRight(function(acc, num, i, orig) {
        if ("-" === num && 0 === i) {
            return num + acc;
        }
        var pos = orig.length - i - 1
        return  num + (pos && !(pos % 3) ? "," : "") + acc;
    }, "") + (p[1] ? "." + p[1] : "");
}

Quelques exemples:

format(77.03453, 2); // "77.03"
format(78436589374); // "78,436,589,374"
format(784, 4);      // "784.0000"
format(-123456);     // "-123,456"
3
Wayne Burkett

Juste pour les futurs googleurs (ou pas nécessairement 'googlers'):

Toutes les solutions mentionnées ci-dessus sont fantastiques, cependant, RegExp pourrait être une très mauvaise chose à utiliser dans une situation comme celle-là.

Donc, oui, vous pouvez utiliser certaines des options proposées ou même écrire quelque chose de primitif et pourtant utile comme:

const strToNum = str => {

   //Find 1-3 digits followed by exactly 3 digits & a comma or end of string
   let regx = /(\d{1,3})(\d{3}(?:,|$))/;
   let currStr;

   do {
       currStr = (currStr || str.split(`.`)[0])
           .replace( regx, `$1,$2`)
   } while (currStr.match(regx)) //Stop when there's no match & null's returned

   return ( str.split(`.`)[1] ) ?
           currStr.concat(`.`, str.split(`.`)[1]) :
           currStr;

};

strToNum(`123`) // => 123
strToNum(`123456`) // => 123,456
strToNum(`-1234567.0987`) // => -1,234,567.0987

L'expression rationnelle utilisée ici est relativement simple et la boucle correspond exactement au nombre de fois nécessaire pour que le travail soit effectué.

Et vous pourriez l'optimiser beaucoup mieux, code "DRYify" et ainsi de suite.

Encore,

(-1234567.0987).toLocaleString();

(dans la plupart des situations) serait un bien meilleur choix.

Le point n'est pas dans la vitesse d'exécution ou dans la compatibilité entre les navigateurs.

Dans les situations où vous souhaitez afficher le nombre obtenu à l'utilisateur, la méthode .toLocaleString () vous donne le pouvoir de parler la même langue avec l'utilisateur de votre site Web ou de votre application (quelle que soit sa langue).

Cette méthode, selon la documentation ECMAScript, a été introduite en 1999, et j'estime que la raison en était l'espoir qu'Internet puisse un jour relier les gens du monde entier. Il fallait donc des outils "d'internalisation".

Aujourd'hui, Internet nous connecte tous. Il est donc important de rappeler que le monde est un moyen beaucoup plus complexe que nous pourrions imaginer et que (/ presque) nous sommes tous ici, sur Internet .

De toute évidence, compte tenu de la diversité des personnes, il est impossible de garantir une UX parfaite pour tout le monde car nous parlons des langues différentes, nous valorisons des choses différentes, etc. C'est pourquoi, il est encore plus important d'essayer de localiser les choses autant que possible. .

Donc, étant donné qu'il existe des normes particulières pour la représentation de la date, de l'heure, des chiffres, etc. & que nous disposons d'un outil pour afficher ces éléments dans le format préféré par l'utilisateur final, n'est-ce pas rare et presque irresponsable? utiliser cet outil (en particulier dans les situations où nous voulons afficher ces données à l'utilisateur)?

Pour moi, utiliser RegExp au lieu de .toLocaleString () dans une telle situation ressemble un peu à créer une application d'horloge avec JavaScript et à le coder de manière à afficher le temps de Prague uniquement (ce qui serait tout à fait inutile pour personnes qui ne vivent pas à Prague) même si le comportement par défaut de

new Date();

est de renvoyer les données en fonction de l'horloge de l'utilisateur final.

2
Igor Bykov

Je pense que votre solution est l'une des plus courtes que j'ai vues pour cela. Je ne pense pas qu'il existe des fonctions JavaScript standard pour faire ce genre de choses, alors vous êtes probablement seul.

J'ai vérifié les spécifications CSS 3 pour voir s'il était possible de le faire en CSS, mais à moins de vouloir chaque chiffre dans son propre <span>, je ne pense pas que ce soit possible.

J'ai trouvé un projet sur code Google qui semblait prometteur: formatage flexible-js . Je ne l'ai pas utilisé, mais il semble assez flexible et comporte des tests unitaires utilisant JsUnit . Le développeur a également beaucoup de messages (bien que vieux) sur ce sujet.

Veillez à prendre en compte les utilisateurs internationaux: de nombreux pays utilisent un espace comme séparateur et utilisent la virgule pour séparer la décimale de la partie intégrante du nombre.

2
jasonmp85

Ma true solution d'expressions régulières pour les one one liners love

Vous voyez ces joueurs enthousiastes ci-dessus? Peut-être que vous pouvez jouer au golf. Voici mon coup.

n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " ").replace(/(?<=\.(\d{3})+)\B/g, " ")

Utilise un ESPACE MINCE (U + 2009) pour un séparateur de milliers, comme le Système international d'unités dit le faire dans la huitième édition(2006) de leur publication “ Brochure SI: Le Système international d’unités (SI) (voir § 5.3.4.). La neuvième édition(2019) suggère d'utiliser un espace pour cela (voir § 5.4.4.). Vous pouvez utiliser ce que vous voulez, y compris une virgule.


Voir.

const integer_part_only = n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ");
const fractional_part_only = n => `${n}`.replace(/(?<=\.(\d{3})+)\B/g, " F ");
const both = n => fractional_part_only(integer_part_only(n));

function demo(number) { // I’m using Chrome 74.
        console.log(`${number}
                → "${integer_part_only(number)}" (integer part only)
                → "${fractional_part_only(number)}" (fractional part only)
                → "${both(number)}" (both)
        `);
}
demo(Math.random() * 10e5);
demo(123456789.01234567);
demo(123456789);
demo(0.0123456789);

Comment ça marche?

Pour une partie entière

.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ")
  • .replace(……, " I ") Mettez "je"
    • /……/g à chacun des
      • \B L'entre-deux chiffres adjacents
        • (?=……)REGARD POSITIF dont la partie droite est
          • (\d{3})+ un ou plusieurs morceaux de trois chiffres
          • \b suivi d'un non-chiffre, tel qu'un point, la fin de la chaîne, et cetera,
        • (?<!……)REGARD NÉGATIF à l'exclusion de ceux dont la partie gauche
          • \.\d+ est un point suivi de chiffres ("possède un séparateur décimal").

Pour une partie décimale

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ") Mettez “F”
    • /……/g à chacun des
      • \B L'entre-deux chiffres adjacents
        • (?<=……)REGARD POSITIF dont la partie gauche est
          • \. un séparateur décimal
          • (\d{3})+ suivi d'un ou de plusieurs morceaux de trois chiffres.

classes de caractères et limites

\d

Correspond à n'importe quel chiffre (chiffre arabe). Équivalent à [0-9].

Par exemple,

  • /\d/ ou /[0-9]/ correspond à 2 dans B2 is the suite number.

\b

Correspond à une limite de mots . C'est la position où un caractère Word n'est pas suivi ou précédé d'un autre caractère Word, tel qu'entre une lettre et un espace. Notez qu'une limite de mot correspondante n'est pas incluse dans la correspondance. En d'autres termes, la longueur d'une limite de mot correspondante est égale à zéro.

Exemples:

  • /\bm/ correspond à la m dans moon;
  • /oo\b/ ne correspond pas à la oo dans moon, car oo est suivi de n qui est un caractère Word;
  • /oon\b/ correspond à la oon dans moon, car oon est la fin de la chaîne, elle n'est donc pas suivie d'un caractère Word;
  • /\w\b\w/ ne correspondra jamais à rien, car un caractère Word ne peut jamais être suivi à la fois d'un caractère autre que Word et d'un caractère Word.

\B

Correspond à une limite autre que Word . Il s'agit d'une position dans laquelle le caractère précédent et le caractère suivant sont du même type: les deux doivent être des mots ou les deux doivent être des non-mots. Comme entre deux lettres ou entre deux espaces. Le début et la fin d'une chaîne sont considérés comme des non-mots. Identique à la limite de mot correspondante, la limite non-mot correspondante n'est pas incluse dans la correspondance.

Par exemple,

  • /\Bon/ correspond à on dans at noon;
  • /ye\B/ correspond à ye dans possibly yesterday.

Compatibilité du navigateur

La solution de @ user1437663 est excellente.

Qui comprend vraiment que la solution est en cours de préparation pour comprendre les expressions régulières complexes.

Une petite amélioration pour le rendre plus lisible:

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

Le modèle commence par \ B pour éviter d'utiliser une virgule au début d'un mot. Fait intéressant, le modèle est retourné vide car \ B n'avance pas le "curseur" (il en va de même pour $).

O \ B est suivi de ressources moins connues mais est une fonctionnalité puissante des expressions régulières de Perl.

            Pattern1 (? = (Pattern2) ).

La magie est que ce qui est entre parenthèses ( Pattern2 ) est un motif qui suit le motif précédent ( Pattern1 ) mais sans faire avancer le curseur et ne fait pas non plus partie du motif renvoyé. C'est une sorte de modèle futur. C'est semblable quand quelqu'un regarde en avant mais ne marche vraiment pas!

Dans ce cas pattern2 est

\d{3})+(?=$)

Cela signifie 3 chiffres (une ou plusieurs fois) suivis de la fin de la chaîne ($)

Enfin, la méthode Replace modifie toutes les occurrences du modèle trouvé (chaîne vide) pour une virgule. Cela ne se produit que dans les cas où la pièce restante est un multiple de 3 chiffres (tels que les cas où le futur curseur atteint la fin de l'Origine).

2
Paulo Buchsbaum

J'ai trouvé une approche qui fonctionne dans toutes les situations. exemple de CodeSandbox

function commas(n) {
  if (n < 1000) {
    return n + ''
  } else {
    // Convert to string.
    n += ''

    // Skip scientific notation.
    if (n.indexOf('e') !== -1) {
      return n
    }

    // Support fractions.
    let i = n.indexOf('.')
    let f = i == -1 ? '' : n.slice(i)
    if (f) n = n.slice(0, i)

    // Add commas.
    i = n.length
    n = n.split('')
    while (i > 3) n.splice((i -= 3), 0, ',')
    return n.join('') + f
  }
}

Cela ressemble à réponse de Noah Freitas , mais avec prise en charge de fractions et de notation scientifique .

Je pense que toLocaleString est le meilleur choix si les performances ne sont pas une préoccupation.

edit: Voici un CodeSandbox avec quelques exemples: https://codesandbox.io/s/zmvxjpj6x

1
aleclarson

J'ai adapté votre code pour qu'il fonctionne dans la zone de texte (type d'entrée = "texte") afin que nous puissions entrer et supprimer des chiffres en temps réel sans perdre le curseur. Cela fonctionne aussi si vous sélectionnez une plage lorsque vous supprimez. Et vous pouvez utiliser les flèches et les boutons home/end librement.
Merci de me faire gagner du temps!

//function controls number format as "1,532,162.3264321"
function numberWithCommas(x) {
    var e = e || window.event;
    if (e.keyCode >= '35' && e.keyCode <= '40') return; //skip arrow-keys
    var selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positions
    var parts = x.value.toString().split(".");
    var part0len = parts[0].length; //old length to check if new ',' would be added. Need for correcting new cursor position (+1 to right).

    //if user deleted ',' - remove previous number instead (without selection)
    if (x.selectionLength == 0 && (e.keyCode == 8 || e.keyCode == 46)) {//if pressed 8-backspace or 46-delete button
        var delPos = parts[0].search(/\d{4}/);
        if (delPos != -1) {//if found 4 digits in a row (',' is deleted)
            if (e.keyCode == 8) {//if backspace flag
                parts[0] = parts[0].slice(0, selStart - 1) + parts[0].slice(selEnd, parts[0].length);
                selEnd--;
                if (selStart > selEnd) selStart = selEnd;
            } else {
                parts[0] = parts[0].slice(0, selStart) + parts[0].slice(selEnd + 1, parts[0].length);
                selStart++;
                if (selEnd < selStart) selEnd = selStart;
            }
        }
    }

   var hasMinus = parts[0][0] == '-';
   parts[0] = (hasMinus ? '-' : '') + parts[0].replace(/[^\d]*/g, ""); //I'd like to clear old ',' to avoid things like 1,2,3,5,634.443216
   parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digits
   if (part0len < parts[0].length) { //move cursor to right if added new ','
       selStart++;
       selEnd++;
   } else if (part0len > parts[0].length) { //..or if removed last one ','
       selStart--;
       selEnd--;
   }
   x.value = parts.join(".");
   x.setSelectionRange(selStart, selEnd); //restoring cursor position
}
function saveSelectionLength(x) {
    x.selectionLength = x.selectionEnd - x.selectionStart;
}

Pour utiliser cela vient d'ajouter deux événements - onKeyUp et onKeyDown

<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>
1
Eluny

Si vous utilisez AngularJS, il existe un filtre monétaire qui peut certainement aider: http://www.w3schools.com/angular/ng_filter_currency.asp

1
Yuxuan Chen

Après ne pas avoir trouvé de solution moderne et complète ici, j’ai écrit une fonction de flèche (sans regex) pour résoudre le problème de formatage et elle permet à l’appelant de fournir le nombre de chiffres décimaux ainsi que le période et millier de séparateur pour l'Europe et le reste du monde.

Exemples:

numberFormatter(1234567890.123456) => 1,234,567,890
numberFormatter(1234567890.123456, 4) => 1,234,567,890.1235
numberFormatter(1234567890.123456, 4, '.', ',') => 1.234.567.890,1235 Europe

Voici la fonction écrite en ES6 (syntaxe moderne):

const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => {
    if (number!==0 && !number || !Number.isFinite(number)) return number
    const frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0
    const num = number.toFixed(frDigits).toString()

    const parts = num.split('.')
    let digits = parts[0].split('').reverse()
    let sign = ''
    if (num < 0) {sign = digits.pop()}
    let final = []
    let pos = 0

    while (digits.length > 1) {
        final.Push(digits.shift())
        pos++
        if (pos % 3 === 0) {final.Push(thousandSeperator)}
    }
    final.Push(digits.shift())
    return `${sign}${final.reverse().join('')}${frDigits > 0 ? fractionSeperator : ''}${frDigits > 0 && parts[1] ? parts[1] : ''}`
}

Il a été testé pour les cas négatif, mauvaise entrée et NaN. Si l'entrée est NaN, il la renvoie simplement.

1

Voici une fonction d'une ligne avec support int & decimal. J'ai laissé du code pour convertir le nombre en chaîne également.

    function numberWithCommas(x) {
        return (x=x+'').replace(new RegExp('\\B(?=(\\d{3})+'+(~x.indexOf('.')?'\\.':'$')+')','g'),',');
    }
0
arosolino

Ce code suivant fonctionne pour moi

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

Pour les entiers, j'ai utilisé une méthode très simple:

var myNumber = 99999,
    myString = myNumber + "";

myString.length > 3 ? return myString.substring(0, myString.length - 3) + "," + 
    myString.substring(myString.length - 3) : return myString;
0
Zakhar

Voici mon essai:

EDIT: Ajouté en décimales

function splitMille(n, separator = ',') {
  // Cast to string
  let num = (n + '')

  // Test for and get any decimals (the later operations won't support them)
  let decimals = ''
  if (/\./.test(num)) {
    // This regex grabs the decimal point as well as the decimal numbers
    decimals = num.replace(/^.*(\..*)$/, '$1')
  }
  
  // Remove decimals from the number string
  num = num.replace(decimals, '')
    // Reverse the number string through Array functions
    .split('').reverse().join('')
    // Split into groups of 1-3 characters (with optional supported character "-" for negative numbers)
    .match(/[0-9]{1,3}-?/g)
    // Add in the mille separator character and reverse back
    .join(separator).split('').reverse().join('')

  // Put the decimals back and output the formatted number
  return `${num}${decimals}`
}

let testA = splitMille(1234)
let testB = splitMille(-1234)
let testC = splitMille(123456.789)
let testD = splitMille(9007199254740991)
let testE = splitMille(1000.0001)

console.log('Results!\n\tA: %s\n\tB: %s\n\tC: %s\n\tD: %s\n\tE: %s', testA, testB, testC, testD, testE)
0
Matt Scheurich

Pour système numérique indien

var number = "323483.85"
var decimal = number.split(".");
var res = (decimal[0].length>3? numberWithCommas(decimal[0].substring(0,decimal[0].length-3))+ ',' :decimal[0]) + (decimal[0].length>3?decimal[0].substring(decimal[0].length-3,decimal[0].length):'') + '.' + decimal[1];

Sortie: 3,23,483,85

0
Saksham

Je pensais partager un petit truc que j'utilise pour le formatage de grands nombres. Au lieu d’insérer des virgules ou des espaces, j’insère une plage vide mais visible entre les "milliers". Cela rend des milliers facilement visibles, mais cela permet de copier/coller l’entrée au format original, sans virgule ni espace.

// This function accepts an integer, and produces a piece of HTML that shows it nicely with 
// some empty space at "thousand" markers. 
// Note, these space are not spaces, if you copy paste, they will not be visible.
function valPrettyPrint(orgVal) {
  // Save after-comma text, if present
  var period = orgVal.indexOf(".");
  var frac = period >= 0 ? orgVal.substr(period) : "";
  // Work on input as an integer
  var val = "" + Math.trunc(orgVal);
  var res = "";
  while (val.length > 0) {
    res = val.substr(Math.max(0, val.length - 3), 3) + res;
    val = val.substr(0, val.length - 3);
    if (val.length > 0) {
        res = "<span class='thousandsSeparator'></span>" + res;
    }
  }
  // Add the saved after-period information
  res += frac;
  return res;
}

Avec ce CSS:

.thousandsSeparator {
  display : inline;
  padding-left : 4px;
}

Voir un exemple JSFiddle.

0
Marcin Zukowski

Ma réponse est la seule réponse qui remplace complètement jQuery par une alternative beaucoup plus judicieuse:

function $(dollarAmount)
{
    const locale = 'en-US';
    const options = { style: 'currency', currency: 'USD' };
    return Intl.NumberFormat(locale, options).format(dollarAmount);
}

Si vous ne souhaitez pas que le premier signe dollar apparaisse sur le montant, vous pouvez également ajouter cette fonction, qui utilise la fonction précédente mais supprime le $:

function no$(dollarAmount)
{
    return $(dollarAmount).replace('$','');
}

Cette solution ajoute non seulement des virgules, mais arrondit également au centime le plus proche si vous saisissez un montant tel que $(1000.9999) pour un montant de 1 001,00 $. De plus, la valeur que vous entrez peut être un nombre ou une chaîne en toute sécurité. ça n'a pas d'importance.

Oh, et d'ailleurs, le fait que ce code ne fonctionne pas dans une ancienne version d'Internet Explorer est totalement intentionnel. J'essaie de casser IE à tout moment, car je ne peux pas l'attraper sans respecter les normes modernes.

N'oubliez pas que les éloges excessifs, dans la section commentaire, sont considérés comme hors sujet. Au lieu de cela, juste me couvrir avec des votes positifs.

0
Lonnie Best

Voici une bonne solution avec moins de codage ...

var y = "";
var arr = x.toString().split("");
for(var i=0; i<arr.length; i++)
{
    y += arr[i];
    if((arr.length-i-1)%3==0 && i<arr.length-1) y += ",";
}
0
Mosiur