Comment formater les nombres en chaîne monétaire?

1849

Je souhaite formater un prix en JavaScript. Je voudrais une fonction qui prend un floatcomme argument et renvoie un stringformaté comme ceci:

"$ 2,500.00"

Quelle est la meilleure façon de procéder?

Daniel Magliola
la source
8
Il n'y a pas de fonction intégrée formatNumberen javascript
zerkms
500
S'il vous plaît, à tous ceux qui liront ceci à l'avenir, n'utilisez pas float pour stocker de la monnaie. Vous perdrez la précision et les données. Vous devez le stocker sous la forme d'un nombre entier de cents (ou de pennies, etc.), puis le convertir avant la sortie.
Philip Whitehouse
8
@ user1308743 Float ne stocke pas de décimales. Il stocke les nombres en utilisant une valeur, une base et un décalage. 0,01 n'est pas réellement représentable. Voir: en.wikipedia.org/wiki/Floating_point#Accuracy_problems
Philip Whitehouse
6
@ user1308743: Imaginez que vous représentez un très grand nombre (disons que vous avez de la chance et que c'est le solde de votre compte bancaire). Souhaitez-vous vraiment perdre de l'argent en raison d'un manque de précision?
avant
163
Alors, pourquoi personne n'a suggéré ce qui suit? (2500) .toLocaleString ("en-GB", {style: "currency", devise: "GBP", minimumFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nick Grealy

Réponses:

1793

Number.prototype.toFixed

Cette solution est compatible avec tous les principaux navigateurs:

  const profits = 2489.8237;

  profits.toFixed(3) //returns 2489.824 (rounds up)
  profits.toFixed(2) //returns 2489.82
  profits.toFixed(7) //returns 2489.8237000 (pads the decimals)

Tout ce dont vous avez besoin est d'ajouter le symbole monétaire (par exemple "$" + profits.toFixed(2)) et vous aurez votre montant en dollars.

Fonction personnalisée

Si vous avez besoin d'utiliser ,entre chaque chiffre, vous pouvez utiliser cette fonction:

function formatMoney(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;

return sign +
	(j ? i.substr(0, j) + thouSep : "") +
	i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "$1" + thouSep) +
	(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}

document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>

Utilisez-le comme ceci:

(123456789.12345).formatMoney(2, ".", ",");

Si vous allez toujours utiliser "." et ',', vous pouvez les laisser hors de votre appel de méthode, et la méthode les par défaut pour vous.

(123456789.12345).formatMoney(2);

Si votre culture a les deux symboles inversés (c'est-à-dire les Européens) et que vous souhaitez utiliser les valeurs par défaut, collez simplement les deux lignes suivantes dans la formatMoneyméthode:

    d = d == undefined ? "," : d, 
    t = t == undefined ? "." : t, 

Fonction personnalisée (ES6)

Si vous pouvez utiliser la syntaxe ECMAScript moderne (c'est-à-dire via Babel), vous pouvez utiliser cette fonction plus simple à la place:

function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
  try {
    decimalCount = Math.abs(decimalCount);
    decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

    const negativeSign = amount < 0 ? "-" : "";

    let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
    let j = (i.length > 3) ? i.length % 3 : 0;

    return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
  } catch (e) {
    console.log(e)
  }
};
document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>

haykam
la source
26
tout d'abord, un code excellent et concis. cependant, si vous êtes américain, vous devez modifier les valeurs par défaut de det têtre .et ,respectivement afin de ne pas avoir à les spécifier à chaque fois. aussi, je recommande de modifier le début de la returndéclaration pour lire return s + '$' + [rest]:, sinon vous n'obtiendrez pas de signe dollar.
Jason
744
Je ne sais pas pourquoi les gens pensent que ce code est beau. C'est indéchiffrable. Cela semble bien fonctionner, mais ce n'est pas beau.
usr
86
Cette fonction formatMoney est-elle copiée à partir d'un code JavaScript minifié quelque part? Pouvez-vous pas poster l'original? Que représentent les variables c, d, i, j, n, s et t? À en juger par le nombre de votes positifs et de commentaires que ce post a, je peux supposer que ce code a été copié dans les sites de production partout ... Bonne chance pour le maintien du code s'il a un bug un jour!
zuallauz
259
"poésie"? Plus comme l'obscurité. Ce n'est pas du golf de code; utilisez un petit espace blanc. De bons noms var ne feraient pas de mal non plus.
keithjgrant
1517

Intl.numberformat

Javascript a un formateur de nombres (qui fait partie de l'API Internationalisation).

// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
});

formatter.format(2500); /* $2,500.00 */

JS fiddle

Utilisez undefinedà la place du premier argument ( 'en-US'dans l'exemple) pour utiliser les paramètres régionaux du système (les paramètres régionaux de l'utilisateur au cas où le code s'exécute dans un navigateur). Explication supplémentaire du code de paramètres régionaux .

Voici une liste des codes de devise .

Intl.NumberFormat vs Number.prototype.toLocaleString

Une dernière note comparant cela à l'ancien. toLocaleString. Ils offrent tous deux essentiellement la même fonctionnalité. Cependant, toLocaleString dans ses anciennes incarnations (pré-Intl) ne prend pas réellement en charge les paramètres régionaux : il utilise les paramètres régionaux du système. Par conséquent, assurez-vous que vous utilisez la bonne version ( MDN suggère de vérifier l'existence deIntl ). De plus, les performances des deux sont les mêmes pour un seul élément, mais si vous avez beaucoup de nombres à formater, l'utilisation Intl.NumberFormatest 70 fois plus rapide. Voici comment utiliser toLocaleString:

(2500).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD',
}); /* $2,500.00 */

Quelques notes sur la prise en charge du navigateur

  • La prise en charge des navigateurs n'est plus un problème de nos jours avec une prise en charge de 97,5% dans le monde, 98% aux États-Unis et 99% dans l'UE
  • Il existe une cale pour le prendre en charge sur les navigateurs fossilisés (comme IE8), si vous en avez vraiment besoin
  • Jetez un œil à CanIUse pour plus d'informations
aross
la source
89
Cette solution JavaScript idomatique, simple et élégante est exactement ce que je cherchais.
Guilhem Soulas
9
Voter celui-ci parce que c'est une réponse stupidement simple qui fonctionne nativement.
Trasiva
17
À peu près sûr, un pourcentage assez élevé de navigateurs le prennent désormais en charge. Cela devrait être beaucoup plus voté.
flq
2
C'est une excellente réponse et je la fais travailler avec une valeur de devise dynamique, donc si l'utilisation est en Europe, elle change en EUR et affiche le signe euro. Fonctionne un régal!
Sprose
3
Nous sommes en 2018 et cela est essentiellement pris en charge partout. Ce devrait être la bonne réponse.
Sarink
1340

Solution courte et rapide (fonctionne partout!)

(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');  // 12,345.67

L'idée derrière cette solution est de remplacer les sections correspondantes par la première correspondance et la virgule, c'est-à-dire '$&,'. L'appariement est effectué en utilisant l' approche Lookahead . Vous pouvez lire l'expression comme "correspondre à un nombre s'il est suivi d'une séquence de trois ensembles de nombres (un ou plusieurs) et un point" .

TESTS:

1        --> "1.00"
12       --> "12.00"
123      --> "123.00"
1234     --> "1,234.00"
12345    --> "12,345.00"
123456   --> "123,456.00"
1234567  --> "1,234,567.00"
12345.67 --> "12,345.67"

DÉMO: http://jsfiddle.net/hAfMM/9571/


Solution courte étendue

Vous pouvez également étendre le prototype d' Numberobjet pour ajouter une prise en charge supplémentaire de n'importe quel nombre de décimales [0 .. n]et de la taille des groupes de nombres [0 .. x]:

/**
 * Number.prototype.format(n, x)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of sections
 */
Number.prototype.format = function(n, x) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};

1234..format();           // "1,234"
12345..format(2);         // "12,345.00"
123456.7.format(3, 2);    // "12,34,56.700"
123456.789.format(2, 4);  // "12,3456.79"

DÉMO / TESTS: http://jsfiddle.net/hAfMM/435/


Solution courte super étendue

Dans cette version super étendue, vous pouvez définir différents types de délimiteurs:

/**
 * Number.prototype.format(n, x, s, c)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of whole part
 * @param mixed   s: sections delimiter
 * @param mixed   c: decimal delimiter
 */
Number.prototype.format = function(n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
        num = this.toFixed(Math.max(0, ~~n));

    return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};

12345678.9.format(2, 3, '.', ',');  // "12.345.678,90"
123456.789.format(4, 4, ' ', ':');  // "12 3456:7890"
12345678.9.format(0, 3, '-');       // "12-345-679"

DÉMO / TESTS: http://jsfiddle.net/hAfMM/612/

VisioN
la source
21
En fait , je suis allé plus loin: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,").
kalisjoshua
4
Version CoffeeScript avec VisioN & kalisjoshua regexp et façon de spécifier la décimale (vous pouvez donc laisser la valeur par défaut de 2 ou spécifier 0 sans décimale):Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Eric Anderson
11
@Abbas Oui, remplacez \.par $(fin de ligne), c'est-à-dire this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,").
VisioN
2
@hanumant La grammaire régulière est un peu compliquée ici, donc je vous suggère de lire d'abord les manuels sur les expressions régulières (par exemple chez MDN ). L'idée derrière cela est de remplacer les sections correspondantes par la première correspondance et la virgule, c'est-à-dire $1,. L'appariement est effectué en utilisant l' approche Lookahead . Vous pouvez lire l'expression comme "correspondre à un nombre s'il est suivi d'une séquence de trois ensembles de nombres (un ou plusieurs) et un point" .
VisioN
2
@ JuliendePrabère Veuillez donner un exemple d'un nombre long qui ne fonctionne pas avec cette approche.
VisioN
248

Jetez un œil à l' objet JavaScript Number et voyez s'il peut vous aider.

  • toLocaleString() formatera un nombre en utilisant un séparateur de milliers spécifique à l'emplacement.
  • toFixed() arrondira le nombre à un nombre spécifique de décimales.

Pour les utiliser en même temps, la valeur doit avoir son type changé de nouveau en nombre car ils produisent tous les deux une chaîne.

Exemple:

Number((someNumber).toFixed(1)).toLocaleString()
17 sur 26
la source
2
Merci! Sur la base de cette idée, j'ai pu en faire une qui soit assez courte et simple! (et localisé) Excellent.
Daniel Magliola
7
En fait, vous le pouvez. c'est-à-dire pour les dollars: '$' + (valeur + 0,001) .toLocaleString (). tranche (0, -1)
Zaptree
6
On dirait que ce serait génial, mais il y a peu de support de navigateur pour le moment
acorncom
1
@acorncom Pourquoi dites-vous qu'il existe un "petit support de navigateur"? L'objet Number existe depuis Javascript 1.1. Veuillez fournir une référence confirmant votre réclamation.
Doug S
2
Il convient de veiller à ce qu'il existe une ancienne version toLocaleStringqui utilise les paramètres régionaux du système et une nouvelle (incompatible) qui provient de l'API ECMAScript Intl. Expliqué ici . Cette réponse semble être destinée à l'ancienne version.
aross
162

Ci-dessous, le code Patrick Desjardins (alias Daok) avec quelques commentaires ajoutés et quelques changements mineurs:

/* 
decimal_sep: character used as deciaml separtor, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{ 
   var n = this,
   c = isNaN(decimals) ? 2 : Math.abs(decimals), //if decimal is zero we must take it, it means user does not want to show any decimal
   d = decimal_sep || '.', //if no decimal separator is passed we use the dot as default decimal separator (we MUST use a decimal separator)

   /*
   according to [/programming/411352/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
   the fastest way to check for not defined parameter is to use typeof value === 'undefined' 
   rather than doing value === undefined.
   */   
   t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, //if you don't want to use a thousands separator you can pass empty string as thousands_sep value

   sign = (n < 0) ? '-' : '',

   //extracting the absolute value of the integer part of the number and converting to string
   i = parseInt(n = Math.abs(n).toFixed(c)) + '', 

   j = ((j = i.length) > 3) ? j % 3 : 0; 
   return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); 
}

et voici quelques tests:

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));

Les changements mineurs sont:

  1. déplacé un peu le Math.abs(decimals)à faire uniquement quand il ne l'est pas NaN.

  2. decimal_sep ne peut plus être une chaîne vide (une sorte de séparateur décimal est un MUST)

  3. nous utilisons typeof thousands_sep === 'undefined'comme suggéré dans Comment déterminer au mieux si un argument n'est pas envoyé à la fonction JavaScript

  4. (+n || 0)n'est pas nécessaire car thisest un Numberobjet

JS Fiddle

Marco Demaio
la source
8
Vous voudrez peut-être utiliser «10» comme radix dans parseInt. Sinon, tout nombre commençant par «0» utilisera la numérotation octale.
sohtimsso1970
3
@ sohtimsso1970: désolé pour la réponse tardive, mais pourriez-vous en expliquer davantage? Je ne vois pas où un nombre pourrait être interprété comme octal. Le parseIntest appelé sur la valeur absolue de la partie INTEGER du nombre. La partie INTEGER ne peut pas commencer par ZERO sauf si c'est juste un ZERO! Et parseInt(0) === 0soit octal ou décimal.
Marco Demaio
essayez, par exemple: parseInt ("016") ... renvoie 14, car parseInt suppose qu'il est codé octal, lorsque la chaîne commence par un zéro.
Tracker1
4
@ Tracker1: J'ai compris qu'un nombre commençant par 0est considéré comme octal par parseInt. Mais dans ce code, il est IMPOSSIBLE parseIntde recevoir 016en entrée (ou toute autre valeur au format octal), car l'argument passé à parseIntest d'abord traité par la Math.absfonction. Il n'y a donc aucun moyen parseIntde recevoir un nombre qui commence par zéro à moins que ce soit juste un zéro ou 0.nn(où nnsont des décimales). Mais les deux 0et les 0.nnchaînes seraient converties parseInten un simple zéro comme supposé être.
Marco Demaio
Ces fonctions sont incorrectes:> (2030) .toMoney (0, '.', ''); <"2 03 0"
Anton P Robul
124

accounting.js est une petite bibliothèque JavaScript pour le formatage des nombres, de l'argent et des devises.

GasheK
la source
... rappelez-vous juste de passer un symbole monétaire sinon il se trompe dans IE7 et IE8, IE9 va bien de toute façon
vecteur
2
Il semble que le bogue IE7 / IE8 soit corrigé.
Mat Schaffer
2
Ceci est une excellente bibliothèque, pouvoir passer le symbole monétaire est également une bonne idée, car tous les détails de la monnaie sont contenus dans l'appel / les paramètres de fonction unique
farinspace
2
J'aime le fait que vous pouvez faire l'inverse - passer une chaîne de devises formatée et obtenir la valeur numérique.
Neil Monroe
2
accounting.js ne semble pas maintenu récemment. Une fourchette avec des changements récents est github.com/nashdot/accounting-js
RationalDev aime GoFundMonica
124

Si le montant est un nombre, disons -123, alors

amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });

produira la chaîne "-$123.00".

Voici un exemple de travail complet .

cs01
la source
7
Cette réponse était presque là pour moi, mais j'avais besoin qu'elle soit arrondie au centime le plus proche. C'est ce que j'ai utilisé amount.toLocaleString ('en-GB', {style: 'currency', devise: 'GBP', maximumFractionDigits: 2});
Nico
Le code ci-dessus arrondit au nombre de chiffres souhaité. Voir l'exemple et tapez 1.237 dans la zone de saisie.
Daniel Barbalace
3
Ne semble pas fonctionner dans Safari. Il renvoie simplement le nombre sous forme de chaîne sans aucune mise en forme.
Lance Anderson
1
Wow, c'est une très bonne réponse. Devrait être top.
Ethan
2
Si pour une raison quelconque vous ne voulez pas de cents, vous pouvez changer la précision décimale avec:minimumFractionDigits: 0
Horacio
99

Voici le meilleur formateur d'argent js que j'ai vu:

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
    var n = this,
        decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
        decSeparator = decSeparator == undefined ? "." : decSeparator,
        thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;
    return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};

Il a été reformaté et emprunté ici: https://stackoverflow.com/a/149099/751484

Vous devrez fournir votre propre indicateur de devise (vous avez utilisé $ ci-dessus).

Appelez-le comme ceci (bien que notez que les arguments par défaut sont 2, virgule et point, donc vous n'avez pas besoin de fournir d'arguments si c'est votre préférence):

var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"
Jonathan M
la source
attention aux signes mondiaux, i, j
hacklikecrack
6
@hacklikecrack, toutes les variables sont locales; ils sont dans la vardéclaration.
Jonathan M
3
désolé, oui, bien que vous redéclariez des arguments. Échancrure! ;)
hacklikecrack
Utilisation horrible des noms de variables!
Serj Sagan
77

Il y a déjà d'excellentes réponses ici. Voici une autre tentative, juste pour le plaisir:

function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    return "$" + p[0].split("").reverse().reduce(function(acc, num, i, orig) {
        return  num=="-" ? acc : num + (i && !(i % 3) ? "," : "") + acc;
    }, "") + "." + p[1];
}

Et quelques tests:

formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"

Modifié: maintenant, il gérera également les nombres négatifs

Wayne Burkett
la source
poésie. brillant. avez-vous essayé ReduceRight () developer.mozilla.org/en/JavaScript/Reference/Global_Objects/… qui devrait éliminer l'inverse ()?
Steve
1
@Steve - Vous avez raison, mais vous devez faire quelque chose comme i = orig.length - i - 1dans le rappel. Pourtant, une traversée de moins du tableau.
Wayne
11
Un pas sur la compatibilité: la reduceméthode a été introduite dans Ecmascript 1.8, et n'est pas prise en charge dans Internet Explorer 8 et ci-dessous.
Blaise
Comme @Blaise l'a dit, cette méthode ne fonctionnera pas dans IE 8 ou inférieur.
rsbarro
Oui, c'est bien sûr exact. Comme indiqué dans la réponse elle-même, c'est juste pour le plaisir. En outre, il devrait très bien gérer les nombres négatifs.
Wayne
76

Fonctionne pour tous les navigateurs actuels

Permet toLocaleStringde formater une devise dans sa représentation sensible à la langue (en utilisant les codes de devise ISO 4217 ).

(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2}) 

Exemple d'extraits de code Rand sud-africains pour @avenmore

console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00

Nick Grealy
la source
1
Parce que les arguments «locales» et «options» ne sont pris en charge que par un très petit nombre de navigateurs, comme Chrome 24, IE11 et Opera 15. Firefox, Safari et les anciennes versions des autres ne le prennent toujours pas en charge.
VisioN
3
D'accord, ce n'est pas encore entièrement pris en charge par tous les navigateurs, mais c'est toujours une solution. (Et sans doute la solution la plus valide, car elle est compatible avec les navigateurs non pris en charge, et c'est une fonctionnalité documentée de l'API Javascript.)
Nick Grealy
1
J'aime cela et je suis heureux que cela fonctionne avec le regroupement de chiffres indiens.
MSC
7
Ceci est entièrement pris en charge à partir de 2017 et devrait être la seule bonne réponse
Evgeny
1
Dernier et meilleur :) FF69, Chrome76, etc. "R 2 500,00" n'est pas ce que nous utilisons ici, il devrait être "R 2 500,00", comme en-GB.
avenmore
70

Je pense que ce que tu veux c'est f.nettotal.value = "$" + showValue.toFixed(2);

écraser
la source
@ écraser cela fonctionne mais il ne porte plus les calculs sur le champ fiscal?
Rocco The Taco
11
Une fois que vous y ajoutez un signe $, ce n'est plus un nombre, mais une chaîne.
écraser le
Cette option ne met pas de virgule entre les milliers. :-(
Simon East
29

Numeral.js - une bibliothèque js pour un formatage facile des nombres par @adamwdraper

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
Yarin
la source
La fourche Numbro semble obtenir plus d'amour alors que Numeral.js semble abandonné: github.com/foretagsplatsen/numbro
RationalDev aime GoFundMonica
Numeral.js est à nouveau actif.
adamwdraper
27

Ok, d'après ce que vous avez dit, j'utilise ceci:

var DecimalSeparator = Number("1.2").toLocaleString().substr(1,1);

var AmountWithCommas = Amount.toLocaleString();
var arParts = String(AmountWithCommas).split(DecimalSeparator);
var intPart = arParts[0];
var decPart = (arParts.length > 1 ? arParts[1] : '');
decPart = (decPart + '00').substr(0,2);

return '£ ' + intPart + DecimalSeparator + decPart;

Je suis ouvert aux suggestions d'amélioration (je préfère ne pas inclure YUI juste pour le faire :-)) Je sais déjà que je devrais détecter le "." au lieu de simplement l'utiliser comme séparateur décimal ...

Daniel Magliola
la source
8
Notez que votre version ne arrondit pas correctement à deux chiffres décimaux. Par exemple, 3.706 serait formaté comme "3.70 £", pas comme "3.71 £" comme il est censé l'être.
Ates Goral
Oui, c'est OK dans mon cas particulier, car les montants avec lesquels je travaille ont déjà au plus 2 chiffres La raison pour laquelle je dois fixer à 2 décimales est pour les montants sans décimales ou avec seulement 1.
Daniel Magliola
26

J'utilise la bibliothèque Globalize (de Microsoft):

C'est un excellent projet pour localiser des nombres, des devises et des dates et les avoir automatiquement formatés de la bonne façon en fonction des paramètres régionaux de l'utilisateur! ... et bien qu'il s'agisse d'une extension jQuery, c'est actuellement une bibliothèque 100% indépendante. Je vous suggère à tous de l'essayer! :)

daveoncode
la source
3
Wow, pourquoi cela n'est-il pas plus voté? Grande bibliothèque standardisée pour toutes sortes de formatage. Paramètres de formatage standard de l'industrie avec une mondialisation correcte. Très bonne réponse!!
pbarranis
Il est toujours considéré comme un stade alpha, alors utilisez-le avec prudence, mais bonne trouvaille.
Neil Monroe
1
Plus en alpha (ou beta). Cela semble être très utile pendant que nous attendons que Safari réponde à la nouvelle norme et que IE <11 meure.
Guy Schalnat
25

javascript-number-formatter (anciennement chez Google Code )

  • Court, rapide, flexible et autonome. Seulement 75 lignes, y compris les informations de licence MIT, les lignes vierges et les commentaires.
  • Acceptez la mise en forme standard des nombres comme #,##0.00ou avec négation -000.####.
  • Acceptez tous les formats de pays comme # ##0,00, #,###.##, #'###.##ou tout type de symbole non-numérotation.
  • Acceptez tout nombre de groupes de chiffres. #,##,#0.000ou #,###0.##sont tous valides.
  • Acceptez tout formatage redondant / infaillible. ##,###,##.#ou 0#,#00#.###0#tout va bien.
  • Arrondi automatique des nombres.
  • Interface simple, masque juste valeur et d'alimentation comme ceci: format( "0.0000", 3.141592).
  • Inclure un préfixe et un suffixe avec le masque

(extrait de son README)

Goodeq
la source
23

+1 à Jonathan M pour avoir fourni la méthode originale. Puisqu'il s'agit explicitement d'un formateur de devises, j'ai continué et ajouté le symbole monétaire (par défaut `` $ '') à la sortie, et ajouté une virgule par défaut comme séparateur de milliers. Si vous ne voulez pas réellement de symbole monétaire (ou de séparateur de milliers), utilisez simplement "" (chaîne vide) comme argument pour cela.

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
    // check the args and supply defaults:
    decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
    decSeparator = decSeparator == undefined ? "." : decSeparator;
    thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
    currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;

    var n = this,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;

    return sign + currencySymbol + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
XML
la source
Le premier var est un peu bizarre, car ces variables sont déjà déclarées dans la déclaration de fonction. A part ça, merci!
Rich Bradshaw
2
Tu as raison. C'est une erreur que j'ai apportée de l'original de Jonathan M, où ils sont tous enchaînés comme une seule expression var. Ces tâches devraient être simples. Fixation.
XML
D'ailleurs, je pense que c'est probablement prématurément optimisé et devrait être refactorisé pour plus de lisibilité. Mais mon objectif était d'augmenter le code de l'OP, pas de le modifier fondamentalement.
XML
Ce n'est pas trop mal - +n || 0c'est la seule chose qui me semble un peu bizarre (de toute façon pour moi).
Rich Bradshaw
2
thisest un nom de variable parfaitement utile. Il npeut être nécessaire de le convertir pour que vous puissiez enregistrer 3 caractères au moment de la définition à une époque où la RAM et la bande passante étaient comptées en Ko, mais il est tout simplement obscur à une époque où le minificateur s'occupe de tout cela avant qu'il n'atteigne jamais la production. Les autres micro-optimisations intelligentes sont au moins discutables.
XML
22

Il existe un port javascript de la fonction PHP "number_format".

Je le trouve très utile car il est facile à utiliser et reconnaissable pour les développeurs PHP.

function number_format (number, decimals, dec_point, thousands_sep) {
    var n = number, prec = decimals;

    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };

    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); 
    //fix for IE parseFloat(0.55).toFixed(0) = 0;

    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;

    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;

        _[0] = s.slice(0,i + (n < 0)) +
               _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }

    var decPos = s.indexOf(dec);
    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
    }
    else if (prec >= 1 && decPos === -1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s; 
}

(Bloc de commentaires de l'original , inclus ci-dessous pour des exemples et des crédits à échéance)

// Formats a number with grouped thousands
//
// version: 906.1806
// discuss at: http://phpjs.org/functions/number_format
// +   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)
// *     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'
DaMayan
la source
Ce n'est qu'une fonction correcte:> nombre_format (2030, 0, '.', '') <'2 030' Génial! Merci
Anton P Robul
21

Une méthode plus courte (pour insérer un espace, une virgule ou un point) avec une expression régulière?

    Number.prototype.toCurrencyString=function(){
        return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g,'$1 ');
    }

    n=12345678.9;
    alert(n.toCurrencyString());
Julien de Prabère
la source
20

Je n'ai rien vu de tel. C'est assez concis et facile à comprendre.

function moneyFormat(price, sign = '$') {
  const pieces = parseFloat(price).toFixed(2).split('')
  let ii = pieces.length - 3
  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, ',')
  }
  return sign + pieces.join('')
}

console.log(
  moneyFormat(100),
  moneyFormat(1000),
  moneyFormat(10000.00),
  moneyFormat(1000000000000000000)
)

Voici une version avec plus d'options dans la sortie finale pour permettre le formatage de différentes devises dans différents formats de localité.

// higher order function that takes options then a price and will return the formatted price
const makeMoneyFormatter = ({
  sign = '$',
  delimiter = ',',
  decimal = '.',
  append = false,
  precision = 2,
  round = true,
  custom
} = {}) => value => {
  
  const e = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]
  
  value = round
    ? (Math.round(value * e[precision]) / e[precision])
    : parseFloat(value)
  
  const pieces = value
    .toFixed(precision)
    .replace('.', decimal)
    .split('')
  
  let ii = pieces.length - (precision ? precision + 1 : 0)
  
  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, delimiter)
  }
  
  if (typeof custom === 'function') {
    return custom({
      sign,
      float: value, 
      value: pieces.join('') 
    })
  }
  
  return append
    ? pieces.join('') + sign
    : sign + pieces.join('')
}

// create currency converters with the correct formatting options
const formatDollar = makeMoneyFormatter()
const formatPound = makeMoneyFormatter({ 
  sign: '£',
  precision: 0
})
const formatEuro = makeMoneyFormatter({
  sign: '€',
  delimiter: '.',
  decimal: ',',
  append: true
})

const customFormat = makeMoneyFormatter({
  round: false,
  custom: ({ value, float, sign }) => `SALE:$${value}USD`
})

console.log(
  formatPound(1000),
  formatDollar(10000.0066),
  formatEuro(100000.001),
  customFormat(999999.555)
)

synthet1c
la source
Excellent extrait de code, merci. Cependant, soyez prudent, car cela ne fonctionnera pas sur IE car les paramètres par défaut ne sont pas pris en charge, et "const" et "let" ne sont pas pris en charge dans <IE11. Utilisez ceci pour corriger: + moneyFormat: function (price, sign) {+ if (! Sign) sign = '$'; + pièces = parseFloat (prix) .toFixed (2) .split ('') + var ii = pièces.longueur - 3
Charlie Dalsass
Pas de soucis @CharlieDalsass. Je recommanderais d'utiliser babel pour le compiler jusqu'à ES5 pour le code de production.
synthet1c
Mais comment faire de l'euro? 1.000,00 Euro?
@YumYumYum J'ai ajouté un exemple complet avec plus d'options de formatage pour permettre plus de flexibilité.
synthet1c
18

La réponse de Patrick Desjardins semble bonne, mais je préfère mon javascript simple. Voici une fonction que je viens d'écrire pour prendre un nombre et le retourner au format monétaire (moins le signe dollar)

// Format numbers to two decimals with commas
function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    var chars = p[0].split("").reverse();
    var newstr = '';
    var count = 0;
    for (x in chars) {
        count++;
        if(count%3 == 1 && count != 1) {
            newstr = chars[x] + ',' + newstr;
        } else {
            newstr = chars[x] + newstr;
        }
    }
    return newstr + "." + p[1];
}
Tim Saylor
la source
J'avais besoin de quelque chose pour fonctionner à la fois dans le navigateur et dans une ancienne version de Node. Cela a parfaitement fonctionné. Merci
n8jadams
17

La partie principale est d'insérer les mille séparateurs, ce qui pourrait être fait comme ceci:

<script type="text/javascript">
function ins1000Sep(val){
  val = val.split(".");
  val[0] = val[0].split("").reverse().join("");
  val[0] = val[0].replace(/(\d{3})/g,"$1,");
  val[0] = val[0].split("").reverse().join("");
  val[0] = val[0].indexOf(",")==0?val[0].substring(1):val[0];
  return val.join(".");
}
function rem1000Sep(val){
  return val.replace(/,/g,"");
}
function formatNum(val){
  val = Math.round(val*100)/100;
  val = (""+val).indexOf(".")>-1 ? val + "00" : val + ".00";
  var dec = val.indexOf(".");
  return dec == val.length-3 || dec == 0 ? val : val.substring(0,dec+3);
}
</script>

<button onclick="alert(ins1000Sep(formatNum(12313231)));">
roenving
la source
J'obtiens une sortie erronée en entrant des valeurs négatives dans ins1000Sep ().
Peter
16

Il est intégré dans function toFixed enjavascript

var num = new Number(349);
document.write("$" + num.toFixed(2));
Porte
la source
Cette réponse semble redondante. La réponse de Crush est déjà mentinotoFixed()
Ian Dunn
3
toFixed()est une fonction de l' Numberobjet et ne fonctionnera pas var numsi c'était un String, donc le contexte supplémentaire m'a aidé.
timborden
15
function CurrencyFormatted(amount)
{
    var i = parseFloat(amount);
    if(isNaN(i)) { i = 0.00; }
    var minus = '';
    if(i < 0) { minus = '-'; }
    i = Math.abs(i);
    i = parseInt((i + .005) * 100);
    i = i / 100;
    s = new String(i);
    if(s.indexOf('.') < 0) { s += '.00'; }
    if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
    s = minus + s;
    return s;
}

De WillMaster .

Bill le lézard
la source
Petit et simple. Je vous remercie.
Connor Simpson
1
simple, mais pas de virgule pour 1000
aron
15

Je suggère la classe NumberFormat de l' API de visualisation Google .

Vous pouvez faire quelque chose comme ça:

var formatter = new google.visualization.NumberFormat({
    prefix: '$',
    pattern: '#,###,###.##'
});

formatter.formatValue(1000000); // $ 1,000,000

J'espère que ça aide.

juanchopx2
la source
14

Cela peut être un peu en retard, mais voici une méthode que je viens de mettre au point pour un collègue pour ajouter une .toCurrencyString()fonction sensible aux paramètres régionaux à tous les nombres. L'internalisation est uniquement pour le regroupement de numéros, PAS le signe de la devise - si vous sortez des dollars, utilisez-les "$"tels qu'ils sont fournis, car $123 4567au Japon ou en Chine, c'est le même nombre d'USD qu'aux $1,234,567États-Unis. Si vous produisez de l'euro / etc., Changez le symbole monétaire de "$".

Déclarez cela n'importe où dans votre HEAD ou partout où cela est nécessaire, juste avant de l'utiliser:

  Number.prototype.toCurrencyString = function(prefix, suffix) {
    if (typeof prefix === 'undefined') { prefix = '$'; }
    if (typeof suffix === 'undefined') { suffix = ''; }
    var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
    return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
  }

Alors vous avez terminé! Utilisez-le (number).toCurrencyString()partout où vous en avez besoin pour sortir le numéro en tant que devise.

var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
Jay Dansand
la source
12

Comme d'habitude, il existe plusieurs façons de faire la même chose, mais j'éviterais de l'utiliser Number.prototype.toLocaleStringcar il peut renvoyer des valeurs différentes en fonction des paramètres utilisateur.

Je ne recommande pas non plus d'étendre le Number.prototype- l'extension des prototypes d'objets natifs est une mauvaise pratique car elle peut provoquer des conflits avec le code d'autres personnes (par exemple bibliothèques / frameworks / plugins) et peut ne pas être compatible avec les futures implémentations / versions JavaScript.

Je crois que les expressions régulières sont la meilleure approche pour le problème, voici ma mise en œuvre:

/**
 * Converts number into currency format
 * @param {number} number   Number that should be converted.
 * @param {string} [decimalSeparator]    Decimal separator, defaults to '.'.
 * @param {string} [thousandsSeparator]    Thousands separator, defaults to ','.
 * @param {int} [nDecimalDigits]    Number of decimal digits, defaults to `2`.
 * @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
 */
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
    //default values
    decimalSeparator = decimalSeparator || '.';
    thousandsSeparator = thousandsSeparator || ',';
    nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;

    var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
        parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]

    if(parts){ //number >= 1000 || number <= -1000
        return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
    }else{
        return fixed.replace('.', decimalSeparator);
    }
}

édité le 30/08/2010: ajout d'une option pour définir le nombre de chiffres décimaux. édité le 23/08/2011: ajout d'une option pour régler le nombre de chiffres décimaux à zéro.

Miller Medeiros
la source
Le point de toLocaleString est qu'il s'ajuste avec les paramètres de l'utilisateur.
Joseph Lennox
11

Voici quelques solutions, toutes réussissent la suite de tests, la suite de tests et le benchmark inclus, si vous voulez copier et coller pour tester, essayez This Gist .

Méthode 0 (RegExp)

Base sur https://stackoverflow.com/a/14428340/1877620 , mais corrigez s'il n'y a pas de point décimal.

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');
        a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
        return a.join('.');
    }
}

Méthode 1

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.'),
            // skip the '-' sign
            head = Number(this < 0);

        // skip the digits that's before the first thousands separator 
        head += (a[0].length - head) % 3 || 3;

        a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
        return a.join('.');
    };
}

Méthode 2 (Split to Array)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');

        a[0] = a[0]
            .split('').reverse().join('')
            .replace(/\d{3}(?=\d)/g, '$&,')
            .split('').reverse().join('');

        return a.join('.');
    };
}

Méthode 3 (boucle)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('');
        a.push('.');

        var i = a.indexOf('.') - 3;
        while (i > 0 && a[i-1] !== '-') {
            a.splice(i, 0, ',');
            i -= 3;
        }

        a.pop();
        return a.join('');
    };
}

Exemple d'utilisation

console.log('======== Demo ========')
console.log(
    (1234567).format(0),
    (1234.56).format(2),
    (-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
    n = (n * 10) + (i % 10)/100;
    console.log(n.format(2), (-n).format(2));
}

Séparateur

Si nous voulons un séparateur de milliers personnalisé ou un séparateur décimal, utilisez replace():

123456.78.format(2).replace(',', ' ').replace('.', ' ');

Suite de tests

function assertEqual(a, b) {
    if (a !== b) {
        throw a + ' !== ' + b;
    }
}

function test(format_function) {
    console.log(format_function);
    assertEqual('NaN', format_function.call(NaN, 0))
    assertEqual('Infinity', format_function.call(Infinity, 0))
    assertEqual('-Infinity', format_function.call(-Infinity, 0))

    assertEqual('0', format_function.call(0, 0))
    assertEqual('0.00', format_function.call(0, 2))
    assertEqual('1', format_function.call(1, 0))
    assertEqual('-1', format_function.call(-1, 0))
    // decimal padding
    assertEqual('1.00', format_function.call(1, 2))
    assertEqual('-1.00', format_function.call(-1, 2))
    // decimal rounding
    assertEqual('0.12', format_function.call(0.123456, 2))
    assertEqual('0.1235', format_function.call(0.123456, 4))
    assertEqual('-0.12', format_function.call(-0.123456, 2))
    assertEqual('-0.1235', format_function.call(-0.123456, 4))
    // thousands separator
    assertEqual('1,234', format_function.call(1234.123456, 0))
    assertEqual('12,345', format_function.call(12345.123456, 0))
    assertEqual('123,456', format_function.call(123456.123456, 0))
    assertEqual('1,234,567', format_function.call(1234567.123456, 0))
    assertEqual('12,345,678', format_function.call(12345678.123456, 0))
    assertEqual('123,456,789', format_function.call(123456789.123456, 0))
    assertEqual('-1,234', format_function.call(-1234.123456, 0))
    assertEqual('-12,345', format_function.call(-12345.123456, 0))
    assertEqual('-123,456', format_function.call(-123456.123456, 0))
    assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
    assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
    assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
    // thousands separator and decimal
    assertEqual('1,234.12', format_function.call(1234.123456, 2))
    assertEqual('12,345.12', format_function.call(12345.123456, 2))
    assertEqual('123,456.12', format_function.call(123456.123456, 2))
    assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
    assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
    assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
    assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
    assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
    assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
    assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
    assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
    assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}

console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);

Référence

function benchmark(f) {
    var start = new Date().getTime();
    f();
    return new Date().getTime() - start;
}

function benchmark_format(f) {
    console.log(f);
    time = benchmark(function () {
        for (var i = 0; i < 100000; i++) {
            f.call(123456789, 0);
            f.call(123456789, 2);
        }
    });
    console.log(time.format(0) + 'ms');
}

// if not using async, browser will stop responding while running.
// this will create a new thread to benchmark
async = [];
function next() {
    setTimeout(function () {
        f = async.shift();
        f && f();
        next();
    }, 10);
}

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
Steely Wing
la source
Amélioré à partir de votre méthode 2. changez de var a = this.toFixed (precision) .split ('.'), À var multiplier = Math.pow (10, precision + 1), wholeNumber = Math.floor (ce * multiplicateur) ; var a = Math.round (wholeNumber / 10) * 10 / multiplier; if (String (a) .indexOf ('.') <1) {a + = '.00'; } a = String (a) .split ('.'), N'utilisez pas toFixed car il est bogué.
vee
console.log (parseFloat ('4.835'). toFixed (2)); > 4.83 console.log (parseFloat ('54 .835 '). ToFixed (2)); > 54.84 console.log (parseFloat ('454.835'). ToFixed (2)); > 454.83 console.log (parseFloat ('8454.835'). ToFixed (2)); > 8454,83 toutes les décimales de ces valeurs doivent être 0,84 et non 0,83
vee
11

Number(value)
        .toFixed(2)
        .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")

Adam Pery
la source
10

Une option simple pour un placement correct des virgules en inversant la chaîne en premier et l'expression rationnelle de base.

String.prototype.reverse = function() {
    return this.split('').reverse().join('');
};

Number.prototype.toCurrency = function( round_decimal /*boolean*/ ) {       
     // format decimal or round to nearest integer
     var n = this.toFixed( round_decimal ? 0 : 2 );

     // convert to a string, add commas every 3 digits from left to right 
     // by reversing string
     return (n + '').reverse().replace( /(\d{3})(?=\d)/g, '$1,' ).reverse();
};
troy
la source
10

J'ai trouvé cela sur: accounting.js . C'est très facile et correspond parfaitement à mon besoin.

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

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

// Negative values can be formatted nicely:
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

// Euro currency symbol to the right
accounting.formatMoney(5318008, {symbol: "€", precision: 2, thousand: ".", decimal : ",", format: "%v%s"}); // 1.008,00€ 

Faysal Haque
la source
$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );- show 1.000,00 E