# In JavaScript, how can you print a number with commas as thousands separators?

## Problem

In JavaScript, I’m trying to output an integer with commas as thousands separators. For instance, I’d like to display the number 1234567 as “1,234,567.” I’m not sure how I’d go about doing this.

Here’s how I’m going about 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 more straightforward or elegant way to go about it? It would be wonderful if it also worked with floats, although this isn’t required. It is not necessary to choose between periods and commas based on your location.

## Solution #1

I took Kerry’s suggestion and simplified it because I was seeking for something basic for a specific purpose. Here’s what I’ve got:

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

Two lookahead assertions are used in the regex:

If you enter 123456789.01, for example, the positive assertion will match every point 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 verifies that the multiple of three digits has no more digits. Because 789 has a period following it, it is an exact multiple of three digits, thus a comma should be used there. 678 is a multiple of three digits, but it has a 9 following it, thus those three digits are part of a group of four, and there is no place for a comma there. Similarly, because 456789 has six digits and is a multiple of three, it is preceded by a comma.

If there are more than three digits following the decimal point, this function puts commas in inappropriate places, according to @neu-rah. If this is an issue, you can use the following function:

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

@t.j.crowder pointed out that now that JavaScript provides lookbehind (support info), the problem can be solved directly in the regular expression:

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

(?!.d*) is a negative lookbehind that states that a. followed by zero or more digits cannot precede the match. At least in V8, the negative lookbehind solution is faster than the split and join solution (compare).

## Solution #2

I’m shocked Number.prototype.toLocaleString wasn’t mentioned. Because it’s written in JavaScript 1.5 (which was released in 1999), it’s supported by almost all major browsers.

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

If you’re looking for something different, Numeral.js might be worth a look.

## Solution #3

Below are two different browser APIs that can transform Numbers into structured Strings. Keep in mind that not all users’ machines have a locale that uses commas in numbers. To enforce commas to the output, any “western” locale may be used, such as en-US

``````let number = 1234567890; // Example number to be converted
``````

Keep in mind that the maximum integer number in javascript is 9007199254740991.

``````// default behaviour on a machine with a local that uses commas for numbers
let number = 1234567890;
number.toLocaleString(); // "1,234,567,890"

// With custom settings, forcing a "US" locale to guarantee commas in output
let number2 = 1234.56789; // floating point example
number2.toLocaleString('en-US', {maximumFractionDigits:2}) // "1,234.57"
``````
``````let number = 1234567890;
let nf = new Intl.NumberFormat('en-US');
nf.format(number); // "1,234,567,890"
``````

According to what I’ve seen (at least in Firefox), they’re about the same in terms of performance.

https://codepen.io/vsync/pen/MWjdbgL?editors=1000 Live demo

## Solution #4

I recommend using number format from 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);
}
``````

UPDATE 02/13/14

People have complained that this does not work as expected, therefore I created a JS Fiddle with automated testing.

Update 26/11/2017

Here’s a Stack Snippet of that tinker, with slightly adjusted output:

## Solution #5

This is an updated version of @mikez302’s response, which now supports numbers with decimals (following @neu-feedback, rah’s 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] : "");
}
``````