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

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,        "0");
failures += !test(100,      "100");
failures += !test(1000,     "1,000");
failures += !test(10000,    "10,000");
failures += !test(100000,   "100,000");
failures += !test(1000000,  "1,000,000");
failures += !test(10000000, "10,000,000");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}


The regex uses two 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,
  • 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:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0              , "0");
failures += !test(0.123456       , "0.123456");
failures += !test(100            , "100");
failures += !test(100.123456     , "100.123456");
failures += !test(1000           , "1,000");
failures += !test(1000.123456    , "1,000.123456");
failures += !test(10000          , "10,000");
failures += !test(10000.123456   , "10,000.123456");
failures += !test(100000         , "100,000");
failures += !test(100000.123456  , "100,000.123456");
failures += !test(1000000        , "1,000,000");
failures += !test(1000000.123456 , "1,000,000.123456");
failures += !test(10000000       , "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

T.J. Crowder pointed out that now that JavaScript has lookbehind (support info), it can be solved in the regular expression itself:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,               "0");
failures += !test(0.123456,        "0.123456");
failures += !test(100,             "100");
failures += !test(100.123456,      "100.123456");
failures += !test(1000,            "1,000");
failures += !test(1000.123456,     "1,000.123456");
failures += !test(10000,           "10,000");
failures += !test(10000.123456,    "10,000.123456");
failures += !test(100000,          "100,000");
failures += !test(100000.123456,   "100,000.123456");
failures += !test(1000000,         "1,000,000");
failures += !test(1000000.123456,  "1,000,000.123456");
failures += !test(10000000,        "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

(?<!\.\d*) is a negative lookbehind that says the match can't be preceded by a . followed by zero or more digits. The negative lookbehind is faster than the split and join solution (comparison), at least in V8.

Answer from Elias Zamaria on Stack Overflow
Top answer
1 of 16
3955

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

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,        "0");
failures += !test(100,      "100");
failures += !test(1000,     "1,000");
failures += !test(10000,    "10,000");
failures += !test(100000,   "100,000");
failures += !test(1000000,  "1,000,000");
failures += !test(10000000, "10,000,000");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}


The regex uses two 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,
  • 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:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0              , "0");
failures += !test(0.123456       , "0.123456");
failures += !test(100            , "100");
failures += !test(100.123456     , "100.123456");
failures += !test(1000           , "1,000");
failures += !test(1000.123456    , "1,000.123456");
failures += !test(10000          , "10,000");
failures += !test(10000.123456   , "10,000.123456");
failures += !test(100000         , "100,000");
failures += !test(100000.123456  , "100,000.123456");
failures += !test(1000000        , "1,000,000");
failures += !test(1000000.123456 , "1,000,000.123456");
failures += !test(10000000       , "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

T.J. Crowder pointed out that now that JavaScript has lookbehind (support info), it can be solved in the regular expression itself:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,               "0");
failures += !test(0.123456,        "0.123456");
failures += !test(100,             "100");
failures += !test(100.123456,      "100.123456");
failures += !test(1000,            "1,000");
failures += !test(1000.123456,     "1,000.123456");
failures += !test(10000,           "10,000");
failures += !test(10000.123456,    "10,000.123456");
failures += !test(100000,          "100,000");
failures += !test(100000.123456,   "100,000.123456");
failures += !test(1000000,         "1,000,000");
failures += !test(1000000.123456,  "1,000,000.123456");
failures += !test(10000000,        "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

(?<!\.\d*) is a negative lookbehind that says the match can't be preceded by a . followed by zero or more digits. The negative lookbehind is faster than the split and join solution (comparison), at least in V8.

2 of 16
3275

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 all major browsers.

var n = 34523453.345;
console.log(n.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.

🌐
Reddit
reddit.com › r/learnjavascript › add dot (.) as a thousands separator as the user types on input
r/learnjavascript on Reddit: Add dot (.) as a thousands separator as the user types on input
August 26, 2022 -

I have a text type input and I’d like for it to show thousands separator with a dot (.) (NOT comma). For example, 1.200 or 125.500

I’ve tried this with a onkeyup event, and I added a regular expression I found online, but the problem is, it adds unnecessary dots. For example, I’ll recreate a user inputting a number:

1 12 120 1.200 1.2.000 1.2.0.000

It’s like it applies it continually but I want the final result to be: 120.000

Is there a way to do this? Maybe it’s not with an onkeyup event on the input tag, maybe it’s something else. But I can’t think of a way.

Thanks. If you need, I’ll look up the regex code I used.

Discussions

What is the best way to handle a period or comma as a thousand or decimal separator in web applications?
The backend should only send raw number, the frontend format depends on locale More on reddit.com
🌐 r/webdev
6
3
August 8, 2023
Add a thousands separator to a total with Javascript or jQuery? - Stack Overflow
I know this is an uber old post and has good answers, BUT if anyone is interested, there is a jQuery plugin which simplifies number formatting (thousands formatting, number of decimal places, custom thousands separator, etc) by making an include and a simple call. More on stackoverflow.com
🌐 stackoverflow.com
Set a specified thousand separator in a formatter | SpreadJS | SpreadJS | MESCIUS Forums
Your query: So I have no way to tell that a number must be formatted using decimal separator and thousand separator of a specific code page, out of the few supported codepages. —> I couldn’t understand your use case. Could you please explain your use case with an example/demo with the steps ... More on developer.mescius.com
🌐 developer.mescius.com
thousand separator (space) and decimal separator (.)
Forum Thread - Pivot Table - thousand separator (space) and decimal separator (.). Browse other users' questions about our JavaScript -... More on syncfusion.com
🌐 syncfusion.com
3
3
October 22, 2020
🌐
Ping Test Tool
hashemian.com › tools › thousand-separator.htm
JavaScript Thousand Separator, Decimal Separator, Decimal Number Formatter
A simple JavaScript function for numerical formatting. It formats decimal numbers by inserting separator characters at the thousands positions. For example, 1234512345.12345 becomes 1,234,512,345.12345.
🌐
W3Resource
w3resource.com › javascript-exercises › javascript-math-exercise-39.php
JavaScript Math: Print an integer with commas as thousands separators - w3resource
July 11, 2025 - num_parts[0] = num_parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); // Join the integer and decimal parts back together with a period and return the result. return num_parts.join("."); } // Output the result of adding thousands separators to ...
🌐
GitHub
gist.github.com › fjaguero › 6932045
JS Regex: Adds thousands separator to a number. · GitHub
This works just fine. "1234567.89" turns into "1.234.567.89" due to the separator is ".", replacing it with "," turns the first value to "1,234,567.89" ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
🌐
Codingexercises
codingexercises.com › format-a-number-with-a-comma-as-a-thousands-separator-js
Format a number with comma as a thousands separator in JS
January 12, 2021 - Here’s an example with a toLocaleString() method: let num = 1234567890; console.log(num.toLocaleString()); // "1,234,567,890" It works with decimal numbers too: Obviously, the above code converts our number into a string, using the local language.
🌐
Phrase
phrase.com › home › resources › blog › how do i convert a decimal to a string with thousands separators?
How Do I Convert a Decimal to a String with Thousands Separators?
January 23, 2025 - Let’s take a look at how to convert a decimal to a string. ... function formatWithThousandsSeparator(num) { let numAsString = num.toString(); let characters = numAsString.split("").reverse(); let parts = []; for (let i = 0; i < characters.length; i += 3) { let part = characters.slice(i, i + 3).reverse().join(""); parts.unshift(part); } return parts.join(","); } This is in JavaScript, but the algorithm can be applied in any language: Split the number into separate characters or strings, one for each digit,
🌐
Reddit
reddit.com › r/webdev › what is the best way to handle a period or comma as a thousand or decimal separator in web applications?
r/webdev on Reddit: What is the best way to handle a period or comma as a thousand or decimal separator in web applications?
August 8, 2023 -

During the period in which I develop fullstack applications, this is exactly what caused me the most problems. And here I am, developing a budget app for expense management - both, a web app and a mobile app, and of course I have problems with these things.

The problem is that it seems to me that there is no universal solution that all browsers and operating systems adhere to.

Even countries do not have a common solution. Europe primarily uses a comma as a decimal separator, and a dot as a thousand separator. in America and Canada it is the other way around, and some countries, such as Switzerland also uses an apostrophe (') as a thousand separator.

Find elsewhere
🌐
npm
npmjs.com › search
keywords:thousand separator - npm search
Use thousand separator (or custom text) to group digits in a string. ... xjpicism• 1.0.1 • 5 years ago • 0 dependents • MITpublished version 1.0.1, 5 years ago0 dependents licensed under $MIT ... A javascript module that scans through string to remove non-numerals and formats out any found numbers based on configuration passed to it.
🌐
David Berri
dberri.com › formatting-numbers-in-javascript
Formatting numbers in JavaScript
November 3, 2021 - So, when I say we are going to ... way to represent numbers is like so: 1.234.567,89. The comma is the decimal separator and the period is the thousands separators....
🌐
Acrobatusers
answers.acrobatusers.com › How-separate-thousands-space-adding-2-decimal-places-q282162.aspx
How to separate thousands with space and adding 2 decimal places (PDF Forms)
var x = Number(event.value).toFixed(2); event.value = x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "); // use space as thousand separator
🌐
Byby
byby.dev › js-format-numbers-commas
How to format numbers with commas in JavaScript
In many English-speaking countries, such as US/UK, the period is used as the decimal separator (eg: 3.14), the comma is used as the thousands separator (eg: 1,000,000).
🌐
Crio
crio.do › blog › format-numbers-with-commas-as-thousands-separators-2025-javascript-criodo
How to Format a Number with Commas as Thousands Separators?
December 26, 2024 - Supports additional options, like setting minimum or maximum decimal places. Additional examples: console.log(num.toLocaleString("en-US", { minimumFractionDigits: 2 })); // "1,234,567.89" console.log(num.toLocaleString("de-DE")); // "1.234.567,89" (German locale) Using Intl.NumberFormat A more advanced method for custom formatting: const formatter = new Intl.NumberFormat("en-US"); console.log(formatter.format(1234567.89)); // Output: "1,234,567.89" Handling Large Numbers JavaScript has a maximum safe integer value (9007199254740991).
🌐
TutorialsPoint
tutorialspoint.com › article › How-to-print-a-number-with-commas-as-thousands-of-separators-in-JavaScript
How to print a number with commas as thousands of separators in JavaScript?
October 20, 2022 - Check for the decimal point and number sign. Remove the sign, loop through, and add commas to 3 digits group accordingly. Add the sign back and display the output. Here, the negative floating point input is processed by the custom code based ...
🌐
Mescius
developer.mescius.com › forums › spreadjs › set-a-specified-thousand-separator-in-a-formatter
Set a specified thousand separator in a formatter | SpreadJS | SpreadJS | MESCIUS Forums
409 and 804 are respectively hexadecimal code page for US and China, and a formatter like “[$-409]ddd mmm yy” will express the day and month always in english, even with a different culture. So my guess was that I can force the culture to any supported codepage by adding [$-xxx] where xxx is the hexa value for the code page. But it seems that it works only for a limited number of codepages, US, China, Japan and Korean, and that the french-swiss code page fr-CH (100C in hexa) is not supported. So I have no way to tell that a number must be formatted using decimal separator and thousand separator of a specific code page, out of the few supported codepages.
🌐
Syncfusion
syncfusion.com › forums › 158969 › thousand-separator-space-and-decimal-separator
thousand separator (space)... | JavaScript - EJ 2 Forums | Syncfusion®
October 22, 2020 - In this following example : https://ej2.syncfusion.com/javascript/demos/#/material/pivot-table/olap.html ... Thousand separator with space, decimal seperator with .
Top answer
1 of 15
246

The reference cited in the original answer below was wrong. There is a built in function for this, which is exactly what kaiser suggests below: toLocaleString

So you can do:

(1234567.89).toLocaleString('en')              // for numeric input
parseFloat("1234567.89").toLocaleString('en')  // for string input

The function implemented below works, too, but simply isn't necessary.

(I thought perhaps I'd get lucky and find out that it was necessary back in 2010, but no. According to this more reliable reference, toLocaleString has been part of the standard since ECMAScript 3rd Edition [1999], which I believe means it would have been supported as far back as IE 5.5.)


Original Answer

According to this reference there isn't a built in function for adding commas to a number. But that page includes an example of how to code it yourself:

function addCommas(nStr) {
    nStr += '';
    var x = nStr.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

Edit: To go the other way (convert string with commas to number), you could do something like this:

parseFloat("1,234,567.89".replace(/,/g,''))
2 of 15
139

If is about localizing thousands separators, delimiters and decimal separators, go with the following:

// --> numObj.toLocaleString( [locales [, options] ] )
parseInt( number ).toLocaleString();

There are several options you can use (and even locales with fallbacks):

number = 123456.7089;

result  = parseInt( number ).toLocaleString() + "<br>";
result += number.toLocaleString( 'de-DE' ) + "<br>";
result += number.toLocaleString( 'ar-EG' ) + "<br>";
result += number.toLocaleString( 'ja-JP', { 
  style           : 'currency',
  currency        : 'JPY',
  currencyDisplay : 'symbol',
  useGrouping     : true
} ) + "<br>";
result += number.toLocaleString( [ 'jav', 'en' ], { 
  localeMatcher            : 'lookup',
  style                    : 'decimal',
  minimumIntegerDigits     : 2,
  minimumFractionDigits    : 2,
  maximumFractionDigits    : 3,
  minimumSignificantDigits : 2,
  maximumSignificantDigits : 3
} ) + "<br>";

var el = document.getElementById( 'result' );
el.innerHTML = result;
<div id="result"></div>

Details on the MDN info page.

Edit: Commentor @I like Serena adds the following:

To support browsers with a non-English locale where we still want English formatting, use value.toLocaleString('en'). Also works for floating point.

🌐
JavaScript in Plain English
javascript.plainenglish.io › javascript-number-formatting-2597725c8c56
JavaScript—Number Formatting. Learn How to Format Numbers With… | by Ange Loron | Medium | JavaScript in Plain English
May 1, 2024 - JavaScript—Number Formatting Learn How to Format Numbers With Thousands Separators in JavaScript When writing numbers, one just expects to have thousand separators but things are not that simple …