I am trying to print an integer in JavaScript with commas as thousands separators. For example, I want to show the number 1234567 as "1,234,567". How would I go about doing this?

Here is how I am doing it:

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

Is there a simpler or more elegant way to do it? It would be nice if it works with floats also, but that is not necessary. It does not need to be locale-specific to decide between periods and commas.

  • 80
    Number(x).toLocaleString()– BoffinMar 9 '15 at 23:04
  • @Boffin this is not working for input type number (because of commas) - in accepted answer we can replace comma to dot and input type number will work– Vitaly ZdanevichAug 16 '15 at 13:10
  • 40
    Worth noting that Number.prototype.toLocaleString still does not work in Safari, in 2016. Instead of actually formatting the number, it just returns it, no error thrown. Having the biggest facepalm today as a result of that... #goodworkApple– aendrewMar 10 '16 at 11:21
  • However, it does appear to work in iOS safari.– TimMay 26 '17 at 19:54
  • toLocaleString is inconsistent and should not be used. For example - on Firefox this will return 1,234 but on IE this will add decimals: 1,234.00– BortSep 21 '17 at 16:29

42 Answers42

up vote2161down voteaccepted

I used the idea from Kerry's answer, but simplified it since I was just looking for something simple for my specific purpose. Here is what I did:

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

This is all you really need to know.

@Neils Bom asked how the regex works. My explanation is sort of long. It won't fit in the comments and I don't know where else to put it so I am doing it here. If anyone has any other suggestions for where to put it, please let me know.

The regex uses 2 lookahead assertions: a positive one to look for any point in the string that has a multiple of 3 digits in a row after it, and a negative assertion to make sure that point only has exactly a multiple of 3 digits. The replacement expression puts a comma there.

For example, if you pass it "123456789.01", the positive assertion will match every spot to the left of the 7 (since "789" is a multiple of 3 digits, "678" is a multiple of 3 digits, "567", etc.). The negative assertion checks that the multiple of 3 digits does not have any digits after it. "789" has a period after it so it is exactly a multiple of 3 digits, so a comma goes there. "678" is a multiple of 3 digits but it has a "9" after it, so those 3 digits are part of a group of 4, and a comma does not go there. Similarly for "567". "456789" is 6 digits, which is a multiple of 3, so a comma goes before that. "345678" is a multiple of 3, but it has a "9" after it, so no comma goes there. And so on. The "\B" keeps the regex from putting a comma at the beginning of the string.

@neu-rah mentioned that this function adds commas in undesirable places if there are more than 3 digits after the decimal point. If this is a problem, you can use this function:

const numberWithCommas=(x)=> {var parts=x.toString().split(".");parts[0]=parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");return parts.join(".");}
  • 27
    This is really awesome! Thanks for distilling Kerry's answer down to exactly what I needed. Thanks! This is a much more elegant solution to what I was originally working on.– Mike GraceJan 24 '11 at 9:08
  • 16
    Very cool, did notice that it has problems with numbers that have more than 3 places after the decimal point though.– Eric PetroeljeFeb 23 '12 at 18:34
  • 51
    try numberWithCommas(12345.6789) -> "12,345.6,789" i dont like it– neu-rahMay 27 '12 at 13:28
  • 22
    Small improvement that fix after '.' problem '123456789.01234'.replace(/\B(?=(?=\d*\.)(\d{3})+(?!\d))/g, '_')– Dmitrij GolubevJun 17 '13 at 9:29
  • 6
    @DmitrijGolubev Doesn't work for integers. Perhaps forcing the decimal point would be the solution.– VladJan 20 '15 at 16:13

I'm surprised nobody mentioned Number.prototype.toLocaleString.It's implemented in JavaScript 1.5 (which was introduced in 1999) so it's basically supported across major browsers.

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

It also works in Node.js as of v0.12 via inclusion of Intl

If you want something different, Numeral.js might be interesting.

  • 11
    @csigrist Good points, but it's not as bad as it seems. Speed is browser dependent. In FF or Opera it performs good. I sucks in Chrome though. As for zeroes: var number=123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00" Those options don't work in FF or Safari though.– uKolkaJul 23 '13 at 15:50
  • 43
    Doesn't seem to work in Safari either.– lambinatorJul 30 '13 at 18:22
  • 18
    The performance difference may or may not be an issue, depending on the context. If used for a giant table of 1000 results then it will be more important but if only used for a single value, the difference is negligible. But the advantage is that it's locale-aware, so someone in Europe would see 34.523.453,345 or 34 523 453,345. This would be more important on a site with visitors from many countries.– T NguyenFeb 12 '14 at 21:06
  • 8
    +1 for numeral.js 👍– BradeMay 7 '14 at 13:38
  • 17
    Update for googlers: toLocaleString works in Node.js as of v0.12 via the inclusion of Intl.– srobinsonNov 2 '15 at 16:59
var number=1234567890; // Example number to be converted

⚠ Mind that javascript has a maximum integer value of 9007199254740991


toLocaleString:

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


NumberFormat (Safari not supported):

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

From what I checked (Firefox at least) they are both more or less same regarding performance.

  • 5
    NumberFormat is not supported on Safari, for anyone who is implementing there.– marcovegaNov 12 '15 at 1:53
  • 4
    toLocaleString is also not supported on safari– Deepak BankaFeb 1 '16 at 8:12
  • 3
    Browsers support is always mentioned at the bottom of each MDN page, which I've linked to.– vsyncMar 19 '16 at 16:38
  • 4
    basic toLocaleString works on safari, options don't– dandavisJun 21 '16 at 9:16
  • 3
    the toLocaleString solution should probably also include the desired locale, so toLocaleString("en"), because the English pattern uses commas. However, if toLocaleString() without locale indicator is run in France, then it'll yield periods instead of commas because that's what is used to separate thousands locally.– Mike 'Pomax' KamermansNov 17 '16 at 18:05

I suggest using phpjs.org 's number_format()

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

UPDATE 02/13/14

People have been reporting this doesn't work as expected, so I did a JS Fiddle that includes automated tests.

Update 26/11/2017

Here's that fiddle as a Stack Snippet with slightly modified output:

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

  • Not that I marked it down, but I believe people did so because it does not work. As it stands I find even some of your tests to not work.– Andrew SJun 19 '13 at 11:51
  • 3
    @Andrew S -- Only 1 person has marked it down. It does work, I have used it in my own code many times. It's also not my code (nor my tests), I referenced the site that it comes from, which is a well-known site. Perhaps they have an updated version of it) as the code you are looking at is 3 years old.– Kerry JonesJun 19 '13 at 18:03
  • 12
    @ernix - The operator asked for JavaScript, that answer I gave is JavaScript. This is a JavaScript interpretation of a PHP function.– Kerry JonesJan 23 '14 at 6:04
  • 2
    @ernix - it works exactly as expected with the example the OP gave. I put a fiddle so you can see.– Kerry JonesFeb 13 '14 at 17:12
  • 4
    @ernix - Okay, but the point is that it does exactly what the OP asked for. It is from another site (not maintained by me, and I've stated this previously), and when giving it proper variables, it works exactly as stated. If you believe that to be a bug, contact phpjs.org or see if they have an updated version.– Kerry JonesFeb 13 '14 at 20:06

This is a variation of @mikez302's answer, but modified to support numbers with decimals (per @neu-rah's feedback that numberWithCommas(12345.6789) -> "12,345.6,789" instead of "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,665print(formatNumber(102665)); // 102,665print(formatNumber(111102665)); // 111,102,665
  • What does this do that my answer doesn't? The regex looks slightly different but it looks like it should do the same thing.– Elias ZamariaAug 19 '14 at 22:14
  • 8
    it's shorter :)– TutankhamenAug 19 '14 at 22:38
  • 4
    This is elegant. Exactly what I was looking for.– traditionalOct 7 '14 at 18:23
  • 4
    From blog.tompawlak.org/number-currency-formatting-javascript? Known issue: formatNumber(0.123456)=0.123,456 The absence of lookbehind in JS makes it difficult to fix it with an elegant regex.– VladJan 20 '15 at 2:48
  • even works with time! 1,234:56– seanJul 22 '15 at 13:56

Using Regular expression

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

Using toLocaleString()

var number=123456.789;// request a currency formatconsole.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));// → 123.456,79 €// the Japanese yen doesn't use a minor unitconsole.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))// → ¥123,457// limit to three significant digitsconsole.log(number.toLocaleString('en-IN', { maximumSignificantDigits: 3 }));// → 1,23,000

ref MDN:Number.prototype.toLocaleString()

Using 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 unitconsole.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));// expected output: "¥123,457"// limit to three significant digitsconsole.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));// expected output: "1,23,000"

ref Intl.NumberFormat

DEMO AT HERE

<script type="text/javascript">// Using Regular expressionfunction toCommas(value) {return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");}function commas() {var num1=document.myform.number1.value;// Using Regular expressiondocument.getElementById('result1').value=toCommas(parseInt(num1));// Using toLocaleString()document.getElementById('result2').value=parseInt(num1).toLocaleString('ja-JP', {style: 'currency',currency: 'JPY'});// Using Intl.NumberFormat()document.getElementById('result3').value=new Intl.NumberFormat('ja-JP', {style: 'currency',currency: 'JPY'}).format(num1);}</script><FORM NAME="myform"><INPUT TYPE="text" NAME="number1" VALUE="123456789"><br><INPUT TYPE="button" NAME="button" Value="=>" onClick="commas()"><br>Using Regular expression<br><INPUT TYPE="text" ID="result1" NAME="result1" VALUE=""><br>Using toLocaleString()<br><INPUT TYPE="text" ID="result2" NAME="result2" VALUE=""><br>Using Intl.NumberFormat()<br><INPUT TYPE="text" ID="result3" NAME="result3" VALUE=""></FORM>

Performance

Performancehttp://jsben.ch/sifRd

  • This doesn't work if you are dynamically typing. If you just give it a value it works, but if you're feeding a value constantly dynamically the commas are added in the wrong place.– Edgar QuinteroAug 16 at 22:46
  • I have updated the demo below my answer. When entering a dynamic value in a textbox. you test try @EdgarQuintero– TinhNQAug 17 at 1:32

Thanks to everyone for their replies. I have built off of some of the answers to make a more "one-size-fits-all" solution.

The first snippet adds a function that mimics PHP's number_format() to the Number prototype. If I am formatting a number, I usually want decimal places so the function takes in the number of decimal places to show. Some countries use commas as the decimal and decimals as the thousands separator so the function allows these separators to be set.

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

You would use this as follows:

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

I found that I often needed to get the number back for math operations, but parseFloat converts 5,000 to 5, simply taking the first sequence of integer values. So I created my own float conversion function and added it to the String prototype.

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

Now you can use both functions as follows:

var foo=5000;var fooString=foo.numberFormat(2); // The string 5,000.00var fooFloat=fooString.getFloat(); // The number 5000;console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00
  • 1
    Very nice, I borrowed the first method ;) But it does not produce a correct result when you want to use a European format and the number is fractional. Line 5 should be: var parts=this.toFixed(decimals).toString().split('.');– vbwxJul 10 '13 at 1:13
  • You are right! toFixed() changes the comma to a period and so the '.' should be used instead of var dec_point. Thanks for pointing that out.– J.MoneyJul 11 '13 at 0:40
  • can you make an npm module for this?– chovyJan 10 '14 at 8:08
  • 3
    @J.Money The .toString is unnecessary, toFixed already returns a string.– ArielJul 8 '14 at 7:56
  • I don't know why you've mentioned PHP here at all, or given a prototipical function which already exists– vsyncAug 22 '15 at 8:47

Intl.NumberFormat

Native JS function. Supported by IE11, Edge, latest Safari, Chrome, Firefox, Opera, Safari on iOS and Chrome on Android.

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

I think this is the shortest regular expression that does it:

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

I checked it on a few numbers and it worked.

  • works only well if you dont have float number with more than 3 numbers after the separator in this case a dot. Otherwise it adds a comma also. "1234567890.1234567890".replace(/\B(?=(\d{3})+\b)/g, ",") This would not work for example. Returns "1,234,567,890.1,234,567,890"– MarcioJul 22 '15 at 10:49
  • 1
    Works well for currency though! Just round your digits prior to adding commas.– Kyle ChadhaSep 18 '15 at 18:04
  • 1
    It Adds , After Decimal point : 12.3456".replace(/\B(?=(\d{3})+\b)/g, ",")==12.3,456– Shree TiwariJun 9 '17 at 10:06

Number.prototype.toLocaleString() would have been awesome if it was provided natively by all browsers (Safari).

I checked all other answers but noone seemed to polyfill it. Here is a poc towards that, which is actually a combination of first two answers; if toLocaleString works it uses it, if it doesn't it uses a custom function.

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

  • 1
    Be aware that the polyfill only works with numbers that have at most 3 decimals. For eg: 0.12345 will output 0.12,345. A good implementation for this can be found in the underscore.string– AndyFeb 28 '17 at 14:20
  • you're right, putting a value > 1000 to the if condition fixes that case, however this was a poc and of course better tested versions can be found elsewhere, thanks for pointing out.– SinanFeb 28 '17 at 19:28
  • 1
    It's not sufficient to put value > 1000, because it would be the same for any number and more than 3 decimals. eg 1000.12345 returns 1,000.12,345. Your answer is great and on the right path, but just not complete. I was only trying to point out for other people that may stumble on your answer and just copy/pasta it without testing with different input data.– AndyMar 1 '17 at 7:59
  • 1
    alright, this needed another edit :) I agree, but now at least it should work for the most cases.– SinanMar 1 '17 at 22:17

The thousands separator can be inserted in an international-friendly manner using the browser's Intl object:

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

See MDN's article on NumberFormat for more, you can specify locale behavior or default to the user's. This is a little more foolproof because it respects local differences; many countries use periods to separate digits while a comma denotes the decimals.

Intl.NumberFormat isn't available in all browsers yet, but it works in latest Chrome, Opera, & IE. Firefox's next release should support it. Webkit doesn't seem to have a timeline for implementation.

  • 2
    While this would be awesome if we could use a simple built-in function, it has terrible browser implementation. For Example, IE 8-10 and all Safari doesnt support this– Blaine KastenSep 2 '14 at 14:45
  • @BlaineKasten there's a fully compatible polyfill for older browsers available here: github.com/andyearnshaw/Intl.js it's huge, but it works.– MahnDec 8 '14 at 13:58
  • I wish this worked on Safari.– jtheletterFeb 23 '15 at 22:01
  • 1
    Available via a pollyfill CDN (only returns what is needed based on useragent): cdn.polyfill.io/v2/polyfill.min.js?features=Intl– KevinSep 30 '15 at 22:09
  • Had issues formatting large numbers with toLocaleString, this worked great (with polyfill)– asked_ioAug 23 '16 at 18:58

if you are dealing with currency values and formatting a lot then it might be worth to add tiny accounting.js which handles lot of edge cases and localization:

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

The following code uses char scan, so there's no regex.

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

It shows promising performance: http://jsperf.com/number-formatting-with-commas/5

2015.4.26: Minor fix to resolve issue when num<0. See https://jsfiddle.net/runsun/p5tqqvs3/

  • this doesn't work with commafy(-123456) it gives -,123,456– wrossmckMar 13 '14 at 16:37
  • This is great! Thanks for putting together the jsperf– bfred.itSep 24 '15 at 21:14
  • This snippet is an absolute monster, out performs everything.– NiCk NewmanJan 15 '16 at 5:46

You can either use this procedure to format your currency needing.

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

For more info you can access this link.

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

  • This is the correct, portable, native answer. Wish I could upvote more than once.– Jared SmithJun 21 at 19:48

Here's a simple function that inserts commas for thousand separators. It uses array functions rather than a 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('');};

CodeSandbox link with examples: https://codesandbox.io/s/p38k63w0vq

  • 1
    Hi.. This example is great. But it will put commas for the decimal part too. just an 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( '' ); 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( '' ) + decimalPart; };– Aki143SSep 25 '12 at 7:53

I Wrote this one before stumbling on this post. No regex and you can actually understand the code.

$(function(){function insertCommas(s) {// get stuff before the dotvar d=s.indexOf('.');var s2=d===-1 ? s : s.slice(0, d);// insert commas every 3 digits from the rightfor (var i=s2.length - 3; i > 0; i -=3)s2=s2.slice(0, i) + ',' + s2.slice(i);// append fractional partif (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>

  • Didn't know you can run code on stackoverflow– Gal BrachaJan 28 '15 at 4:48
  • 1
    I added s.toString() at beginning of function so it can accept numbers too, not just strings. This is my preferred answer because it is readable, concise, and has none of the bugs the regex answers seem to have.– FeFiFoFuJan 12 '16 at 23:19
  • Try to put -100000000000000.478 ... doesnt work good– SeraphFeb 15 '16 at 13:04

Let me try to improve uKolka's answer and maybe help others save some time.

Use Numeral.js.

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

You should go with Number.prototype.toLocaleString() only if its browser compatibilty is not an issue.

  • this inspired me to npm install numeral– steampoweredJun 17 '15 at 15:38

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.22alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))

shortcut

1234567.22.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(".");}
      • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.– Donald DuckJun 10 '17 at 19:48
      • Nice script, but it does not work with negative numbers.– Ralph David AbernathyJan 26 at 18:50

      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.347formatNumber(17347, 3)=17.347,000formatNumber(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 <span>, 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.

        • Could you post the solution using CSS only & spans?– Chris BettiDec 11 '13 at 15:14

        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 - 1return 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"
        • this doesn't work with format(-123456) it gives -,123,456– wrossmckMar 13 '14 at 16:37
        • 1
          Fixed (although there is probably a more elegant way to do it without checking for the sign every time). In any event, the update makes this work with negative numbers.– Wayne BurkettMar 13 '14 at 17:39

        Here's my try:

        EDIT: Added in decimals

        function splitMille(n, separator=',') {// Cast to stringlet num=(n + '')// Test for and get any decimals (the later operations won't support them)let decimals=''if (/\http://stackoverflow.com/.test(num)) {// This regex grabs the decimal point as well as the decimal numbersdecimals=num.replace(/^.*(\..*)$/, '$1')}// Remove decimals from the number stringnum=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 numberreturn `${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)

          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<arr.length; i++){y +=arr[i];if((arr.length-i-1)%3==0 && i<arr.length-1) y +=",";}
            • this doesn't work for -123456 it gives -1,234,56– wrossmckMar 13 '14 at 16:35
            • I have updated. pls check.– MosiurMar 14 '14 at 7:37
            • that still doesn't work when the input is -123456. it gives -,123,456 jsfiddle.net/wrossmck/2R8mD/1– wrossmckMar 15 '14 at 13:16
            • 1
              this is just crazy :)– Petr HavlikMay 22 '14 at 23:53
            • Haha I agree with petr its fun to look at though.– nocarrierAug 23 '14 at 19:28

            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<n.length;i+=3) {if(i!=0) f+=ts;f+=n.substr(i,3);}if(dp > 0) f +=ds + number.toFixed(dp).split('.')[1]return f;}
            • Perfect for me, just added a new line to remove formatting before processing.– Dennis HeidenMar 21 '16 at 14:50

            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-keysvar selStart=x.selectionStart, selEnd=x.selectionEnd; //save cursor positionsvar 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)http://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 buttonvar delPos=parts[0].search(/\d{4}/);if (delPos !=-1) {//if found 4 digits in a row (',' is deleted)if (e.keyCode==8) {//if backspace flagparts[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.443216parts[0]=parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digitsif (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

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

              I thought I'd share a little trick which I'm using for large number formatting.Instead of inserting commas or spaces, I insert an empty but visible span in between the "thousands". This makes thousands easily visible, but it allows to copy/paste the input in the original format, without commas/spaces.

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

              With this CSS:

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

              See an example JSFiddle.

              • You could still show commas while allowing copy/paste the input in the original format by using css: .thousandsSeparator:before{ content: ','; } JSFiddle: jsfiddle.net/Dandalf/ze6agw7v– DandalfJun 10 '16 at 20:17
              • Oh wait. It just adds a comma before. Your still render using the Javascript from my example. So I'm not sure what you mean.– Marcin ZukowskiJun 11 '16 at 20:58
              • I have taken this a step further by displaying un-selectable commas: jsfiddle.net/ovfd83py/13– James HulseAug 15 '17 at 9:42

              protected by Community May 25 '15 at 21:56

              Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

              Would you like to answer one of these unanswered questions instead?

              Not the answer you're looking for? Browse other questions tagged or ask your own question.