Como imprimir um número com vírgulas como separadores de milhares em JavaScript

Eu estou tentando imprimir um inteiro em JavaScript com vírgulas como separadores de milhares. Por exemplo, quero mostrar o número 1234567 como “1,234,567”. Como eu iria fazer isso?

Aqui está como eu estou fazendo isso:

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

Existe uma maneira mais simples ou elegante de fazer isso? Seria bom se também funcionasse com flutuadores, mas isso não é necessário. Ele não precisa ser específico de localidade para decidir entre pontos e vírgulas.

Eu usei a ideia da resposta de Kerry, mas simplifiquei desde que eu estava apenas procurando por algo simples para o meu propósito específico. Aqui está o que eu fiz:

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

Isso é tudo que você realmente precisa saber.

@Neils Bom perguntou como funciona o regex. Minha explicação é meio longa. Não cabe nos comentários e não sei mais onde colocá-los, por isso estou fazendo aqui. Se alguém tiver outras sugestões sobre onde colocá-lo, por favor me avise.

O regex usa duas asserções lookahead: uma positiva para procurar por qualquer ponto na string que tenha um múltiplo de 3 dígitos seguidos, e uma afirmação negativa para garantir que o ponto tenha exatamente um múltiplo de 3 dígitos. A expressão de substituição coloca uma vírgula lá.

Por exemplo, se você passar “123456789.01”, a asserção positiva corresponderá a cada ponto à esquerda do 7 (já que “789” é um múltiplo de 3 dígitos, “678” é um múltiplo de 3 dígitos, “567”, etc). A declaração negativa verifica se o múltiplo de 3 dígitos não possui nenhum dígito depois disso. “789” tem um período depois, então é exatamente um múltiplo de 3 dígitos, então uma vírgula vai para lá. “678” é um múltiplo de 3 dígitos, mas tem um “9” depois, então esses 3 dígitos fazem parte de um grupo de 4, e uma vírgula não vai lá. Da mesma forma para “567”. “456789” tem 6 dígitos, o que é um múltiplo de 3, então uma vírgula vai antes disso. “345678” é um múltiplo de 3, mas tem um “9” depois disso, então nenhuma vírgula vai para lá. E assim por diante. O “\ B” mantém o regex de colocar uma vírgula no início da seqüência de caracteres.

@ neu-rah mencionou que esta function adiciona vírgulas em lugares indesejáveis ​​se houver mais de 3 dígitos após o ponto decimal. Se isso é um problema, você pode usar esta function:

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

Estou surpreso que ninguém tenha mencionado Number.prototype.toLocaleString . Ele é implementado no JavaScript 1.5 (que foi introduzido em 1999), então é basicamente suportado pelos principais navegadores.

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

Ele também funciona no Node.js a partir da v0.12 através da inclusão do Intl

Se você quiser algo diferente, o Numeral.js pode ser interessante.

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

⚠ Lembre-se de que o javascript tem um valor inteiro máximo 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 não suportado):

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

Pelo que verifiquei (pelo menos o Firefox), eles são mais ou menos iguais em relação ao desempenho.

Eu sugiro usar o number_format () do 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); } 

ATUALIZAÇÃO 02/13/14

As pessoas têm relatado que isso não funciona como esperado, então eu fiz um JS Fiddle que inclui testes automatizados.

Atualização 26/11/2017

Aqui está o violino como um Snippet de pilha com saída ligeiramente modificada:

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

Esta é uma variação da resposta de @ mikez302, mas modificada para suportar números com decimais (per feedback do @ neu-rah que numberWithCommas (12345.6789) -> “12.345.6,789” em vez 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] : ""); } 
 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 

Obrigado a todos por suas respostas. Eu criei algumas das respostas para criar uma solução mais “tamanho único”.

O primeiro trecho adiciona uma function que imita o number_format() PHP para o protótipo Number. Se estou formatando um número, geralmente quero casas decimais para que a function considere o número de casas decimais a serem mostradas. Alguns países usam vírgulas como decimais e decimais como separador de milhar, então a function permite que esses separadores sejam definidos.

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

Você usaria isso da seguinte maneira:

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

Descobri que muitas vezes precisei recuperar o número para operações matemáticas, mas o parseFloat converte 5.000 para 5, simplesmente obtendo a primeira seqüência de valores inteiros. Então eu criei minha própria function de conversão float e a adicionei ao protótipo 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)); } 

Agora você pode usar as duas funções da seguinte maneira:

 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 

Intl.NumberFormat

Função JS nativa. Compatível com IE11, Edge, Safari mais recente, Chrome, Firefox, Opera, Safari no iOS e Chrome no Android.

 var number = 3500; console.log(new Intl.NumberFormat().format(number)); // → '3,500' if in US English locale 

Acho que esta é a expressão regular mais curta que faz isso:

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

Eu verifiquei em alguns números e funcionou.

Number.prototype.toLocaleString() teria sido incrível se tivesse sido fornecido nativamente por todos os navegadores (Safari) .

Eu chequei todas as outras respostas, mas ninguém pareceu polifilar isso. Aqui está um poc para isso, que é na verdade uma combinação das duas primeiras respostas; se toLocaleString trabalha, ele usa, se não usa uma function customizada.

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

Usando expressão regular

 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 

Usando 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 ()

Usando Intl.NumberFormat ()

 var number = 123456.789; console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number)); // expected output: "123.456,79 €" // the Japanese yen doesn't use a minor unit console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number)); // expected output: "¥123,457" // limit to three significant digits console.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number)); // expected output: "1,23,000" 

ref Intl.NumberFormat

DEMO AQUI

  


Using Regular expression

Using toLocaleString()

Using Intl.NumberFormat()

O separador de milhar pode ser inserido de maneira internacional, usando o object Intl do navegador:

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

Veja o artigo do MDN sobre NumberFormat para mais, você pode especificar o comportamento do código de idioma ou o padrão para o usuário. Isso é um pouco mais infalível porque respeita as diferenças locais; muitos países usam períodos para separar dígitos enquanto uma vírgula indica os decimais.

O Intl.NumberFormat ainda não está disponível em todos os navegadores, mas funciona no Chrome, no Opera e no IE mais recentes. A próxima versão do Firefox deve suportá-lo. O Webkit não parece ter um cronograma para implementação.

Se você está lidando com valores de moeda e formatando muito, então pode valer a pena adicionar tiny accounting.js que lida com muitos casos de borda e localização:

 // 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 

O código a seguir usa verificação de caractere, portanto, não há regex.

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

Mostra desempenho promissor: http://jsperf.com/number-formatting-with-commas/5

2015.4.26: Correção secundária para resolver o problema quando num <0. Veja https://jsfiddle.net/runsun/p5tqqvs3/

Você pode usar esse procedimento para formatar sua moeda.

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

Para mais informações você pode acessar este link.

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

Aqui está uma function simples que insere vírgulas para milhares de separadores. Ele usa funções de matriz em vez de um RegEx.

 /** * Format a number as a string with commas separating the thousands. * @param num - The number to be formatted (eg 10000) * @return A string representing the formatted number (eg "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(''); }; 

Eu escrevi este antes de tropeçar neste post. Não há regex e você pode realmente entender o código.

 $(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' ) ); }); 
  

Deixe-me tentar melhorar a resposta do uKolka e talvez ajudar os outros a economizar algum tempo.

Use Numeral.js .

 document.body.textContent = numeral(1234567).format('0,0'); 
  

For me, the best answer is using toLocaleString like some members said. If you want to include the ‘$’ symbol just add languaje and type options. Here is and example to format a number to Mexican Pesos

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

I think this function will take care of all the issues related to this problem.

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

I added tofixed to Aki143S ‘s solution. This solution uses dots for thousands separators and comma for the precision.

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

Examples;

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

I think your solution is one of the shorter ones I’ve seen for this. I don’t think there are any standard JavaScript functions to do this sort of thing, so you’re probably on your own.

I checked the CSS 3 specifications to see whether it’s possible to do this in CSS, but unless you want every digit in its own , I don’t think that’s possible.

I did find one project on Google Code that looked promising: flexible-js-formatting . I haven’t used it, but it looks pretty flexible and has unit tests using JsUnit . The developer also has a lot of posts (though old) about this topic.

Be sure to consider international users: lots of nations use a space as the separator and use the comma for separating the decimal from the integral part of the number.

Lots of good answers already. Here’s another, just for fun:

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

Some examples:

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

Here’s my try:

EDIT: Added in decimals

 function splitMille(n, separator = ',') { // Cast to string let num = (n + '') // Test for and get any decimals (the later operations won't support them) let decimals = '' if (/\./.test(num)) { // This regex grabs the decimal point as well as the decimal numbers decimals = num.replace(/^.*(\..*)$/, '$1') } // Remove decimals from the number string num = num.replace(decimals, '') // Reverse the number string through Array functions .split('').reverse().join('') // Split into groups of 1-3 characters (with optional supported character "-" for negative numbers) .match(/[0-9]{1,3}-?/g) // Add in the mille separator character and reverse back .join(separator).split('').reverse().join('') // Put the decimals back and output the formatted number return `${num}${decimals}` } let testA = splitMille(1234) let testB = splitMille(-1234) let testC = splitMille(123456.789) let testD = splitMille(9007199254740991) let testE = splitMille(1000.0001) console.log('Results!\n\tA: %s\n\tB: %s\n\tC: %s\n\tD: %s\n\tE: %s', testA, testB, testC, testD, testE) 

After not finding a modern and comprehensive solution here, I have written an arrow function (without regex) to solve the formatting problem and it allows the caller to provide number of fraction digits as well as the period and thousand separator for Europe and rest of the world.

Exemplos:

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

Here is the function written in ES6 (modern syntax):

 const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => { if (number!==0 && !number || !Number.isFinite(number)) return number const frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0 const num = number.toFixed(frDigits).toString() const parts = num.split('.') let digits = parts[0].split('').reverse() let sign = '' if (num < 0) {sign = digits.pop()} let final = [] let pos = 0 while (digits.length > 1) { final.push(digits.shift()) pos++ if (pos % 3 === 0) {final.push(thousandSeperator)} } final.push(digits.shift()) return `${sign}${final.reverse().join('')}${frDigits > 0 ? fractionSeperator : ''}${frDigits > 0 && parts[1] ? parts[1] : ''}` } 

It has been tested for negative, bad input and NaN cases . If the input is NaN then it simply returns it.

The solution from @user1437663 is great.

Who really understands the solution is being prepared to understand complex regular expressions.

A small improvement to make it more readable:

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

The pattern starts with \B to avoid use comma at the beginning of a word. Interestingly, the pattern is returned empty because \B does not advance the “cursor” (the same applies to $ ).

O \B is followed by a less known resources but is a powerful feature from Perl’s regular expressions.

  Pattern1 (? = (Pattern2) ). 

The magic is that what is in parentheses ( Pattern2 ) is a pattern that follows the previous pattern ( Pattern1 ) but without advancing the cursor and also is not part of the pattern returned. It is a kind of future pattern. This is similar when someone looks forward but really doesn’t walk!

In this case pattern2 is

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

It means 3 digits (one or more times) followed by the end of the string ($)

Finally, Replace method changes all occurrences of the pattern found (empty string) for comma. This only happens in cases where the remaining piece is a multiple of 3 digits (such cases where future cursor reach the end of the origin).

Here is good solution with less coding…

 var y = ""; var arr = x.toString().split(""); for(var i=0; i 

An alternative way, supporting decimals, different separators and negatives.

 var number_format = function(number, decimal_pos, decimal_sep, thousand_sep) { var ts = ( thousand_sep == null ? ',' : thousand_sep ) , ds = ( decimal_sep == null ? '.' : decimal_sep ) , dp = ( decimal_pos == null ? 2 : decimal_pos ) , n = Math.abs(Math.ceil(number)).toString() , i = n.length % 3 , f = n.substr(0, i) ; if(number < 0) f = '-' + f; for(;i 0) f += ds + number.toFixed(dp).split('.')[1] return f; } 

I’ve adapted your code to work in TextBox (Input type=”text”) so we can enter and delete digits in real time without losing cursor. It’s works also if you select range when you delete. And you can use arrows and home/end buttons freely.
Thanks for saving my time!

 //function controls number format as "1,532,162.3264321" function numberWithCommas(x) { var e = e || window.event; if (e.keyCode >= '35' && e.keyCode < = '40') return; //skip arrow-keys var selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positions var parts = x.value.toString().split("."); var part0len = parts[0].length; //old length to check if new ',' would be added. Need for correcting new cursor position (+1 to right). //if user deleted ',' - remove previous number instead (without selection) if (x.selectionLength == 0 && (e.keyCode == 8 || e.keyCode == 46)) {//if pressed 8-backspace or 46-delete button var delPos = parts[0].search(/\d{4}/); if (delPos != -1) {//if found 4 digits in a row (',' is deleted) if (e.keyCode == 8) {//if backspace flag parts[0] = parts[0].slice(0, selStart - 1) + parts[0].slice(selEnd, parts[0].length); selEnd--; if (selStart > selEnd) selStart = selEnd; } else { parts[0] = parts[0].slice(0, selStart) + parts[0].slice(selEnd + 1, parts[0].length); selStart++; if (selEnd < selStart) selEnd = selStart; } } } var hasMinus = parts[0][0] == '-'; parts[0] = (hasMinus ? '-' : '') + parts[0].replace(/[^\d]*/g, ""); //I'd like to clear old ',' to avoid things like 1,2,3,5,634.443216 parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digits if (part0len < parts[0].length) { //move cursor to right if added new ',' selStart++; selEnd++; } else if (part0len > parts[0].length) { //..or if removed last one ',' selStart--; selEnd--; } x.value = parts.join("."); x.setSelectionRange(selStart, selEnd); //restoring cursor position } function saveSelectionLength(x) { x.selectionLength = x.selectionEnd - x.selectionStart; } 

To use this just added two events – onKeyUp and onKeyDown