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

1784

J'essaie d'imprimer un entier en JavaScript avec des virgules comme des milliers de séparateurs. Par exemple, je veux afficher le numéro 1234567 comme "1 234 567". Comment pourrais-je procéder?

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

Existe-t-il une manière plus simple ou plus élégante de le faire? Ce serait bien si cela fonctionne avec des flotteurs également, mais ce n'est pas nécessaire. Il n'est pas nécessaire qu'il soit spécifique aux paramètres régionaux pour choisir entre les périodes et les virgules.

Elias Zamaria
la source
156
Number (x) .toLocaleString ()
Boffin
@Boffin, cela ne fonctionne pas pour le numéro de type d'entrée (à cause des virgules) - dans la réponse acceptée, nous pouvons remplacer la virgule par un point et le numéro de type d'entrée fonctionnera
Vitaly Zdanevich
48
À noter que cela ne fonctionne Number.prototype.toLocaleString toujours pas dans Safari, en 2016 . Au lieu de formater réellement le nombre, il le renvoie simplement, sans erreur. Avoir le plus grand facepalm aujourd'hui à la suite de cela ... #goodworkApple
aendrew
Cependant, cela semble fonctionner dans Safari iOS.
Tim
toLocaleString est incohérent et ne doit pas être utilisé. Par exemple - sur Firefox, cela renverra 1 234, mais sur IE, cela ajoutera des décimales: 1 234,00
Bort

Réponses:

2837

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


L'expression régulière utilise 2 assertions d'anticipation:

  • une valeur positive pour rechercher n'importe quel point de la chaîne qui a un multiple de 3 chiffres consécutifs après,
  • une affirmation négative pour vous assurer que ce point n'a exactement qu'un multiple de 3 chiffres. L'expression de remplacement y met une virgule.

Par exemple, si vous la réussissez 123456789.01, l'assertion positive correspondra à chaque point à gauche du 7 (puisqu'il 789s'agit d'un multiple de 3 chiffres, 678est 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. 789a un point après, donc c'est exactement un multiple de 3 chiffres, donc une virgule y va. 678est un multiple de 3 chiffres mais il a un 9après, donc ces 3 chiffres font partie d'un groupe de 4, et une virgule n'y va pas. De même pour 567. 456789est de 6 chiffres, ce qui est un multiple de 3, donc une virgule précède. 345678est un multiple de 3, mais il a un 9après, donc aucune virgule n'y va. 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 aux 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:

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

@ tjcrowder a souligné que maintenant que JavaScript a du retard ( informations de support ), il peut être résolu dans l'expression régulière elle-même:

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

(?<!\.\d*)est un lookbehind négatif qui dit que la correspondance ne peut pas être précédée d'un .suivi de zéro ou plusieurs chiffres. Le lookbehind négatif est plus rapide que la solution splitet join( comparaison ), du moins en V8.

Elias Zamaria
la source
21
Très cool, j'ai remarqué qu'il a des problèmes avec les nombres qui ont plus de 3 places après la virgule décimale.
Eric Petroelje
60
essayez numberWithCommas (12345.6789) -> "12 345,6 789" je n'aime pas ça
neu-rah
4
Cela ne fonctionne pas bien avec les fractions, nous ne voudrions pas avoir de virgules après le point décimal
Mugen
30
Petite amélioration qui corrige après '.' problème '123456789.01234'.replace (/ \ B (? = (? = \ d * \.) (\ d {3}) + (?! \ d)) / g,' _ ')
Dmitrij Golubev
8
@DmitrijGolubev Ne fonctionne pas pour les entiers. Forcer peut-être la virgule décimale serait la solution.
Vlad
1811

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

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

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

Faites juste attention à ce que cette fonction renvoie une chaîne, pas un nombre.

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

uKolka
la source
17
@csigrist Bons points, mais ce n'est pas aussi mauvais qu'il n'y paraît. La vitesse dépend du navigateur. Dans FF ou Opera, il fonctionne bien. Mais j'aspire Chrome. En ce qui concerne les zéros: var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00"ces options ne fonctionnent cependant pas dans FF ou Safari.
uKolka
22
La différence de performances peut ou non être un problème, selon le contexte. S'il est utilisé pour un tableau géant de 1000 résultats, il sera plus important, mais s'il n'est utilisé que pour une seule valeur, la différence est négligeable. Mais l'avantage est qu'il est sensible aux paramètres régionaux, donc quelqu'un en Europe verrait 34.523.453.345 ou 34 523 453.345 . Ce serait plus important sur un site avec des visiteurs de nombreux pays.
T Nguyen
6
Impressionnant. Enfin une réponse avec fonction native. Et de plus, celui-ci s'affiche correctement dans différents pays avec différents séparateurs (en République tchèque, nous écrivons X XXX XXX,YYY).
Tomáš Zato - Reinstate Monica
22
Mise à jour pour googlers: toLocaleStringfonctionne dans Node.js à partir de la v0.12 via l' inclusion d'Intl .
srobinson
8
@MSC vous devriez essayer parseInt("1234567", 10).toLocaleString('en-US', {minimumFractionDigits: 2})ou à la new Number("1234567").toLocaleString('en-US', {minimumFractionDigits: 2})place. Cela ne fonctionne pas car vous l'utilisez sur une chaîne, pas sur un nombre.
uKolka
244
var number = 1234567890; // Example number to be converted

⚠ Gardez à l'esprit que javascript a une valeur entière maximale 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é (Firefox au moins), ils sont tous deux plus ou moins identiques en termes de performances.

vsync
la source
6
NumberFormat n'est pas pris en charge sur Safari, pour tous ceux qui y mettent en œuvre.
marcovega
6
toLocaleString n'est pas non plus pris en charge lors d'un safari
Deepak Banka
3
La prise en charge des navigateurs est toujours mentionnée au bas de chaque page MDN, à laquelle j'ai lié.
vsync
5
les toLocaleStringtravaux de base sur le safari, les options ne le font pas
dandavis
3
la toLocaleStringsolution devrait probablement également inclure les paramètres régionaux souhaités toLocaleString("en"), car le modèle anglais utilise des virgules. Cependant, si l' toLocaleString()indicateur de locale n'est pas exécuté en France, il produira des périodes au lieu de virgules car c'est ce qui est utilisé pour séparer des milliers localement.
Mike 'Pomax' Kamermans
112

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

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 fonctionnait pas comme prévu, j'ai donc fait un JS Fiddle qui comprend des tests automatisés.

Mise à jour 26/11/2017

Voici ce violon en tant qu'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;
}

Kerry Jones
la source
Non pas que je l'ai noté, mais je crois que les gens l'ont fait parce que cela ne fonctionne pas. Dans l'état actuel des choses, même certains de vos tests ne fonctionnent pas.
Andrew S
3
@Andrew S - Seulement 1 personne l'a noté. Cela fonctionne, je l'ai utilisé plusieurs fois dans mon propre code. Ce n'est pas non plus mon code (ni mes tests), j'ai référencé le site dont il est issu, qui est un site bien connu. Peut-être qu'ils en ont une version mise à jour) car le code que vous regardez a 3 ans.
Kerry Jones
13
@ernix - L'opérateur a demandé JavaScript, la réponse que j'ai donnée est JavaScript. Il s'agit d'une interprétation JavaScript d'une fonction PHP.
Kerry Jones
2
@ernix - cela fonctionne exactement comme prévu avec l'exemple donné par l'OP. J'ai mis un violon pour que vous puissiez voir.
Kerry Jones
4
@ernix - D'accord, mais le fait est qu'il fait exactement ce que l'OP a demandé. Il provient d'un autre site (non géré par moi, et je l'ai déjà indiqué), et lorsque vous lui donnez les variables appropriées, cela fonctionne exactement comme indiqué. Si vous pensez que c'est un bug, contactez phpjs.org ou voyez s'ils ont une version mise à jour.
Kerry Jones
75

Il s'agit d'une variante de la réponse de @ mikez302, mais modifiée pour prendre en charge les nombres avec des décimales (selon les commentaires de @ neu-rah 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] : "");
}
user1437663
la source
1
Hé, regardez, vous êtes un contributeur open-source :)
Jacob Stamm
67
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
Toutankhamon
la source
Qu'est-ce que cela fait que ma réponse ne fait pas? Le regex semble légèrement différent, mais il semble qu'il devrait faire la même chose.
Elias Zamaria
8
c'est plus court :)
Toutankhamon
4
C'est élégant. Exactement ce que je cherchais.
traditionnelle
4
De blog.tompawlak.org/number-currency-formatting-javascript ? Problème connu: formatNumber (0.123456) = 0.123,456 L'absence de lookbehind dans JS rend difficile la correction avec une expression régulière élégante.
Vlad
1
123456789.123456789.toString (). Replace (/ (\ d) (? = (\ D {3}) + \.) / G, '$ 1,') => 123,456,789.12345679
kenberkeley
53

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

DÉMO 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

Performance http://jsben.ch/sifRd

Tính Ngô Quang
la source
Cela ne fonctionne pas si vous tapez dynamiquement. Si vous lui donnez simplement une valeur, cela fonctionne, mais si vous alimentez une valeur de manière dynamique en permanence, les virgules sont ajoutées au mauvais endroit.
Edgar Quintero
J'ai mis à jour la démo sous ma réponse. Lors de la saisie d'une valeur dynamique dans une zone de texte. vous testez essayez @EdgarQuintero
Tính Ngô Quang
39

Intl.NumberFormat

Fonction JS native. Pris en charge par IE11, Edge, les derniers 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
Dustin Sun
la source
Ma réponse a été mise à jour en réponse à vos commentaires. Merci!
Dustin Sun
35

Merci à tous pour leurs réponses. J'ai construit à partir de certaines des réponses pour faire une solution plus «taille unique».

Le premier extrait ajoute une fonction qui imite PHP « s number_format()au prototype numérique. Si je mets en forme 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é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 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 trouvé 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 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
Aucun
la source
2
Très bien, j'ai emprunté la première méthode;) Mais ça ne donne pas un résultat correct quand on veut utiliser un format européen et le nombre est fractionnaire. La ligne 5 doit être:var parts = this.toFixed(decimals).toString().split('.');
vbwx
Tu as raison! toFixed () change la virgule en un point et donc le '.' doit être utilisé à la place de var dec_point. Merci d'avoir fait remarquer cela.
Aucun
pouvez-vous créer un module npm pour cela?
chovy
3
@ J.Money Le .toString n'est pas nécessaire, toFixed renvoie déjà une chaîne.
Ariel
Je ne sais pas pourquoi vous avez mentionné PHP ici du tout, ou donné une fonction prototipicale qui existe
vsync
27

Je suis assez impressionné par le nombre de réponses à cette question. J'aime la réponse de uKolka :

n.toLocaleString()

Mais malheureusement, dans certains endroits comme l'espagnol, cela ne fonctionne pas (à mon humble avis) comme prévu pour les nombres inférieurs à 10 000:

Number(1000).toLocaleString('ES-es')

Donne 1000et non1.000 .

Voir toLocaleString ne fonctionnant pas sur des nombres inférieurs à 10000 dans tous les navigateurs pour savoir pourquoi.

J'ai donc dû utiliser la réponse d' Elias Zamaria choisissant le bon séparateur de milliers:

n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Celui-ci fonctionne bien comme une ligne pour les deux paramètres régionaux qui utilisent ,ou. comme séparateur de milliers et commence à fonctionner à partir de 1000 dans tous les cas.

Number(1000).toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Donne 1.000 avec un contexte local espagnol.

Si vous souhaitez avoir un contrôle absolu sur la façon dont un nombre est formaté, vous pouvez également essayer ce qui suit:

let number   = 1234.567
let decimals = 2
let decpoint = '.' // Or Number(0.1).toLocaleString().substring(1, 2)
let thousand = ',' // Or Number(10000).toLocaleString().substring(2, 3)

let n = Math.abs(number).toFixed(decimals).split('.')
n[0] = n[0].split('').reverse().map((c, i, a) =>
  i > 0 && i < a.length && i % 3 == 0 ? c + thousand : c
).reverse().join('')
let final = (Math.sign(number) < 0 ? '-' : '') + n.join(decpoint)

console.log(final)

Donne 1,234.57 .

Celui-ci n'a pas besoin d'une expression régulière. Cela fonctionne en ajustant le nombre à la quantité de décimales souhaitée avec d' toFixedabord, puis en le divisant autour du point décimal. s'il y en a un. Le côté gauche est ensuite transformé en un tableau de chiffres qui est inversé. Ensuite, un séparateur de milliers est ajouté tous les trois chiffres depuis le début et le résultat est inversé à nouveau. Le résultat final est l'union des deux parties. Le signe du numéro saisi est supprimé avecMath.abs abord puis remis si nécessaire.

Ce n'est pas une doublure mais pas beaucoup plus longtemps et facilement transformable en fonction. Des variables ont été ajoutées pour plus de clarté, mais celles-ci peuvent être remplacées par leurs valeurs souhaitées si elles sont connues à l'avance. Vous pouvez utiliser les expressions qui toLocaleStringpermettent de trouver les bons caractères pour le point décimal et le séparateur de milliers pour les paramètres régionaux actuels (gardez à l'esprit que ceux-ci nécessitent un Javascript plus moderne.)

Javier Elices
la source
23

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é.

user3664916
la source
ne fonctionne bien que si vous n'avez pas de nombre flottant avec plus de 3 chiffres après le séparateur dans ce cas un point. Sinon, il ajoute également une virgule. "1234567890.1234567890" .replace (/ \ B (? = (\ D {3}) + \ b) / g, ",") Cela ne fonctionnerait pas par exemple. Renvoie "1 234 567 890,1 234 567 890"
Marcio
1
Fonctionne bien pour la monnaie cependant! Arrondissez simplement vos chiffres avant d'ajouter des virgules.
Kyle Chadha
1
Il ajoute, après le point décimal: 12,3456 ".replace (/ \ B (? = (\ D {3}) + \ b) / g,", ") == 12,3,456
Shree Tiwari
21

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

J'ai vérifié toutes les autres réponses mais personne ne semblait les remplir. Voici un poc vers cela, qui est en fait une combinaison des deux premières réponses; si toLocaleStringcela 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));

Sinan
la source
1
Sachez que le polyfill ne fonctionne qu'avec des nombres qui ont au plus 3 décimales. Par exemple: 0.12345affichera 0.12,345. Une bonne implémentation pour cela peut être trouvée dans le underscore.string
Andy
vous avez raison, mettre un value > 1000à la condition if corrige ce cas, mais c'était un poc et bien sûr, des versions mieux testées peuvent être trouvées ailleurs, merci de le souligner.
Sinan
1
Ce n'est pas suffisant de mettre value > 1000, car ce serait la même chose pour n'importe quel nombre et plus de 3 décimales. par exemple les 1000.12345retours 1,000.12,345. Votre réponse est excellente et sur la bonne voie, mais tout simplement incomplète. J'essayais simplement de signaler à d'autres personnes qui pourraient tomber sur votre réponse et simplement la copier / la coller sans la tester avec différentes données d'entrée.
Andy
1
bien, cela avait besoin d'un autre montage :) Je suis d'accord, mais maintenant au moins cela devrait fonctionner pour la plupart des cas.
Sinan
18

Le séparateur de milliers peut être inséré de manière conviviale à l'international en utilisant l' Intlobjet du navigateur :

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

Voir l'article de MDN sur NumberFormat pour plus d'informations, vous pouvez spécifier le comportement local ou par défaut celui de l'utilisateur. C'est un peu plus à toute épreuve 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 derniers Chrome, Opera et IE. La prochaine version de Firefox devrait la prendre en charge. Webkit ne semble pas avoir de calendrier de mise en œuvre.

phette23
la source
2
Bien que ce soit génial si nous pouvions utiliser une simple fonction intégrée, il a une implémentation terrible du navigateur. Par exemple, IE 8-10 et tous les Safari ne supportent pas cela
Blaine Kasten
@BlaineKasten il y a un polyfill entièrement compatible pour les anciens navigateurs disponible ici: github.com/andyearnshaw/Intl.js c'est énorme, mais ça marche.
Mahn
1
Disponible via un CDN pollyfill (ne renvoie que ce qui est nécessaire en fonction de l'agent utilisateur): cdn.polyfill.io/v2/polyfill.min.js?features=Intl
Kevin
A eu des problèmes de mise en forme de grands nombres avec toLocaleString, cela a très bien fonctionné (avec polyfill)
demandé_io
18

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

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/

Dulith De Costa
la source
Ceci est la bonne réponse, portable et native. J'aimerais pouvoir voter plus d'une fois.
Jared Smith
14

Si vous traitez beaucoup avec des valeurs monétaires et que vous formatez beaucoup, il peut être utile d'ajouter de minuscules accounting.js qui gère beaucoup de cas marginaux 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
Shital Shah
la source
1
Le lien ne fonctionne plus. Mais ressemble à celui-ci: openexchangerates.github.io/accounting.js
ush189
13

Le code suivant utilise l'analyse des caractères, il n'y a donc pas d'expression régulière.

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: correction mineure pour résoudre le problème lorsque num <0. Voir https://jsfiddle.net/runsun/p5tqqvs3/

runun
la source
cela ne fonctionne pas avec commafy(-123456)cela donne-,123,456
wrossmck
C'est bien! Merci d'avoir assemblé le jsperf
fregante
Cet extrait est un monstre absolu, surpasse tout.
NiCk Newman
13

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

Noah Freitas
la source
1
Salut .. Cet exemple est génial. Mais il mettra aussi des virgules pour la partie décimale. juste un edit: function formatNumber (num) {var decimalPart = ''; num = num.toString (); if (num.indexOf ('.')! = -1) {decimalPart = '.' + num.split ('.') [1]; num = parseInt (num.split ('.') [0]); } var array = num.toString (). split (''); indice var = -3; while (array.length + index> 0) {array.splice (index, 0, ','); // Décrémente de 4 puisque nous venons d'ajouter une autre unité au tableau. indice - = 4; } return array.join ('') + decimalPart; };
Aki143S
Merci Monsieur. C'est exactement ce dont j'avais besoin.
Amir Hossein Ahmadi
11

Utilisez ce code pour gérer le format de devise pour l'Inde. Le code du 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);

production:

3,50,256.95
Bathri Nathan
la source
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse. Lisez ceci .
Shanteshwar Inde
@ShanteshwarInde j'ajouterai un contexte supplémentaire pour améliorer la réponse
Bathri Nathan
11

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

 resultNumber = new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(yourNumber); 
Oliver
la source
ce nœud ne fonctionne pas js. Il ne donne pas de réponse au format indien
Suraj Dalvi
7

J'ai écrit celui-ci avant de tomber sur ce post. Aucun 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>

Ronnie Overby
la source
1
J'ai ajouté s.toString () au début de la fonction pour qu'il puisse accepter aussi les nombres, pas seulement les chaînes. C'est ma réponse préférée car elle est lisible, concise et n'a aucun des bugs que les réponses regex semblent avoir.
FeFiFoFu
7
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 exmaple:

var number = -123123231232;
formatNumber(number)

Sortie: "123,123,231,232"

Mais pour répondre à la question ci-dessus, la toLocaleString()méthode ne fait que résoudre le problème.

var number = 123123231232;
    number.toLocaleString()

Sortie: "123,123,231,232"

Acclamation!

Kiry Meas
la source
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Donald Duck
1
Beau script, mais il ne fonctionne pas avec des nombres négatifs.
Ralph David Abernathy
7

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

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

Cette solution ajoute non seulement des virgules, mais elle arrondit également au centime le plus proche dans le cas où vous saisissez un montant comme $(1000.9999)vous obtiendrez 1001,00 $. De plus, la valeur que vous entrez peut être en toute sécurité un nombre ou une chaîne; ça n'a pas d'importance.

Si vous avez affaire à de l'argent, mais que vous ne voulez pas qu'un signe dollar en tête s'affiche sur le montant, vous pouvez également ajouter cette fonction, qui utilise la fonction précédente mais supprime $:

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

Si vous n'avez pas d'argent et que vous avez des exigences de formatage décimal variables, voici une fonction plus polyvalente:

function addCommas(number, minDecimalPlaces = 0, maxDecimalPlaces = Math.max(3,minDecimalPlaces))
{
    const options = {};
    options.maximumFractionDigits = maxDecimalPlaces;
    options.minimumFractionDigits = minDecimalPlaces;
    return Intl.NumberFormat('en-US',options).format(number);
}

Oh, et en passant, le fait que ce code ne fonctionne pas dans une ancienne version d'Internet Explorer est complètement intentionnel. J'essaye de casser IE à tout moment que je peux attraper ne supportant pas les normes modernes.

N'oubliez pas que les louanges excessives, dans la section des commentaires, sont considérées comme hors sujet. Au lieu de cela, arrosez-moi simplement de votes positifs.

Lonnie Best
la source
1
Le numéro (n) .toLocaleString () semble la meilleure réponse, mais vous voudrez probablement utiliser quelque chose comme le nouveau format Intl.NumberFormat ('en-US'). (N) plutôt que de supprimer les signes dollar et les décimales si tous les l'utilisateur veut des virgules dans son numéro.
bmacnaughton
@bmacnaughton: C'est un bon point lorsque vous n'avez pas d'argent. Cependant, si vous avez affaire à de l'argent et que vous ne voulez tout simplement pas le signe du dollar principal, Number (1000.50) .toLocaleString () produit '1,000.5', ce qui supprime le zéro insignifiant généralement conservé lors de l'affichage des valeurs monétaires. Bon commentaire cependant: tout le monde devrait savoir ce que vous avez dit.
Lonnie Best
6

Pour moi, la meilleure réponse est d'utiliser toLocaleString comme certains membres l'ont dit. Si vous souhaitez inclure le symbole «$», ajoutez simplement languaje et tapez les options. Voici et 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"})
Carlos A. Ortiz
la source
5

Permettez-moi d'essayer d'améliorer la réponse d' uKolka et peut-être d'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 ne devez utiliser Number.prototype.toLocaleString () que si la compatibilité de son navigateur n'est pas un problème.

Beder Acosta Borges
la source
cela m'a inspiré à installer npm
numeral
5

Une manière alternative, en prenant en charge les décimales, différents séparateurs et négatifs.

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.floor(Math.abs(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 voter pour son commentaire.

Felipe Buccioni
la source
Parfait pour moi, vient d'ajouter une nouvelle ligne pour supprimer le formatage avant le traitement.
Dennis Heiden
2
fn.substr(0, i)remplacer par n.substr(0, i)et également number.toFixed(dp).split('.')[1]remplacer par parseFloat(number).toFixed(dp).split('.')[1]. parce que quand j'utilise directement ça me donne une erreur. veuillez mettre à jour votre code
Jignesh Sanghani
imparfait. le nombre augmente. un appel d'exampel aurait été formidable!
mmm
le passage du plafond au plancher a corrigé cela, mais ne sait pas quels autres problèmes se poseront.
mmm
1
Essayez Math.floor (-75.1);)
mmm
4

Je pense que cette fonction prendra en charge tous les problèmes liés à 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;
}
AbhinavRanjan
la source
4

Juste pour les futurs Googleurs (ou pas nécessairement les «Googleurs»):

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

Donc, oui, vous pouvez utiliser certaines des options proposées ou même écrire quelque chose de primitif mais 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 assez simple et la boucle ira précisément le nombre de fois qu'il faut pour faire le travail.

Et vous pourriez l'optimiser bien mieux, le code "DRYify", etc.

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 numéro résultant à l'utilisateur, la méthode .toLocaleString () vous donne le super pouvoir de parler la même langue avec l'utilisateur de votre site Web ou application (quelle que soit sa langue).

Cette méthode, selon la documentation ECMAScript, a été introduite en 1999, et je pense que cela s'expliquait par l'espoir qu'Internet, à un moment donné, connectera les gens du monde entier, donc, certains outils "d'internalisation" étaient nécessaires.

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

Évidemment, compte tenu de la diversité des personnes, il est impossible de garantir une UX parfaite pour tout le monde parce que nous parlons différentes langues, valorisons des choses différentes, etc. Et précisément à cause de cela, 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 nombres, etc. et que nous avons un outil pour afficher ces choses dans le format préféré par l'utilisateur final, n'est-ce pas rare et presque irresponsable de ne pas utiliser cet outil (surtout dans les situations où nous voulons afficher ces données à l'utilisateur)?

Pour moi, utiliser RegExp au lieu de .toLocaleString () dans une situation comme celle-ci ressemble un peu à créer une application d'horloge avec JavaScript et à la coder en dur de telle sorte qu'elle n'affichera que l'heure de Prague (ce qui serait tout à fait inutile pour personnes qui ne vivent pas à Prague) même si le comportement par défaut de

new Date();

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

Igor Bykov
la source
pourquoi avez-vous écrit la fonction avec const et =>?
OG Sean
@OGSean Je le fais toujours car c'est le moyen le plus pratique de déclarer des variables et des fonctions. De plus, je pense que cela aide à garder le code plus propre et plus court.
Igor Bykov
4

Ma « vraie » solution d'expressions régulières pour ceux qui aiment les lignes simples

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 l'a dit 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) propose d'y utiliser un espace (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
      • \B l'entre-deux de deux chiffres adjacents
        • (?=……)LOOKAHEAD POSITIF dont la partie droite est
          • (\d{3})+ un ou plusieurs morceaux à trois chiffres
          • \b suivi d'un non-chiffre, comme un point, la fin de la chaîne, et cetera,
        • (?<!……)REGARD NÉGATIF excluant ceux dont la partie gauche
          • \.\d+ est un point suivi de chiffres («a un séparateur décimal»).

Pour une partie décimale

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ") Mettez "F"
    • /……/g à chacun
      • \B l'entre-deux de deux chiffres adjacents
        • (?<=……)REGARD POSITIF dont la partie gauche est
          • \. un séparateur décimal
          • (\d{3})+ suivi d'un ou plusieurs morceaux à 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à B2 is the suite number.

\b

Correspond à une limite de mot . Il s'agit de la position où un caractère de mot n'est pas suivi ou précédé d'un autre caractère de mot, comme entre une lettre et un espace. Notez qu'une limite de mot correspondant n'est pas incluse dans la correspondance. En d'autres termes, la longueur d'une limite de mot correspondant est nulle.

Exemples:

  • /\bm/correspond à l' mentrée moon;
  • /oo\b/ne correspond pas à ooin moon, car ooest suivi par nlequel est un caractère de mot;
  • /oon\b/correspond à oonin moon, car oonest la fin de la chaîne, donc non suivie d'un caractère de mot;
  • /\w\b\w/ ne correspondra à rien, car un caractère de mot ne peut jamais être suivi à la fois d'un caractère non-mot et d'un caractère de mot.

\B

Correspond à une limite autre qu'un mot . Il s'agit d'une position où le caractère précédent et suivant sont du même type: soit les deux doivent être des mots, soit 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 de non-mot correspondante n'est pas non plus incluse dans la correspondance.

Par exemple,

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

Compatibilité du navigateur

Константин Ван
la source
3

J'ai ajouté tofixed à la solution d' Aki143S . Cette solution utilise des points pour des milliers de séparateurs et des virgules 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
Bartburkhardt
la source
3

Beaucoup de bonnes réponses déjà. En voici une 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"
Wayne
la source
cela ne fonctionne pas avec format(-123456)cela donne-,123,456
wrossmck
1
Corrigé (bien qu'il existe probablement une manière plus élégante de le faire sans vérifier le signe à chaque fois). En tout état de cause, la mise à jour rend cela possible avec des nombres négatifs.
Wayne