186

I want to format numbers using JavaScript.

For example:

10     => 10.00
100    => 100.00
1000   => 1,000.00
10000  => 10,000.00
100000 => 100,000.00
Michael
  • 8,362
  • 6
  • 61
  • 88
Kanak Vaghela
  • 7,750
  • 10
  • 32
  • 37

17 Answers17

297

If you want to use built-in code, you can use toLocaleString() with minimumFractionDigits.

Browser compatibility for the extended options on toLocaleString() was limited when I first wrote this answer, but the current status looks good. If you're using Node.js, you will need to npm install the intl package.

var value = (100000).toLocaleString(
  undefined, // leave undefined to use the visitor's browser 
             // locale or a string like 'en-US' to override it.
  { minimumFractionDigits: 2 }
);
console.log(value);

Number formatting varies between cultures. Unless you're doing string comparison on the output,1 the polite thing to do is pick undefined and let the visitor's browser use the formatting they're most familiar with.2

// Demonstrate selected international locales
var locales = [
  undefined,  // Your own browser
  'en-US',    // United States
  'de-DE',    // Germany
  'ru-RU',    // Russia
  'hi-IN',    // India
  'de-CH',    // Switzerland
];
var n = 100000;
var opts = { minimumFractionDigits: 2 };
for (var i = 0; i < locales.length; i++) {
  console.log(locales[i], n.toLocaleString(locales[i], opts));
}

If you are from a culture with a different format from those above, please edit this post and add your locale code.


1 Which you shouldn't.
2 Obviously do not use this for currency with something like {style: 'currency', currency: 'JPY'} unless you have converted to the local exchange rate. You don't want your website to tell people the price is ¥300 when it's really $300. Sometimes real e-commerce sites make this mistake.

Community
  • 1
  • 1
Michael
  • 8,362
  • 6
  • 61
  • 88
  • 1
    I wanted to use built in code and this got me there. The locales options is a small issue I'm willing to live with. I think this should be the accepted answer because it takes into account the locale nuances of number rendition. – Alexander Dixon Aug 10 '17 at 19:51
  • 2
    Beware that `toLocaleString` is very slow and can leak memory in Node! Tested this on Node 10.16.3: ```console.log('on start RSS = ', process.memoryUsage().rss / 1024 / 1024); const number = Math.random() * 10; const params = { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }; for (let i = 0; i < 100000; i++) { Number(number).toLocaleString('en-US', params); } console.log('on end RSS = ', process.memoryUsage().rss / 1024 / 1024); ``` – Dmitriy T Sep 06 '19 at 18:45
59

Use

num = num.toFixed(2);

Where 2 is the number of decimal places

Edit:

Here's the function to format number as you want

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

Sorce: www.mredkj.com

Ortiga
  • 8,455
  • 5
  • 42
  • 71
  • 3
    But using .toFixed(2) i will not get the result for 10000 and 100000 as 10,000.00 and 1,00,000.00 – Kanak Vaghela Apr 20 '11 at 13:40
  • 1
    Simple and fast! This needed to be the best answer! – Weslley Rufino de Lima Jul 08 '22 at 16:57
  • To understand more easily, I changed the name of the variables. function formatNumber(number) { number= number.toFixed(2); brokenNumbersPostPoint= number.split('.'); numbersBeforePoint= brokenNumbersPostPoint[0]; numbersAfterPoint= brokenNumbersPostPoint.length > 1 ? '.' + brokenNumbersPostPoint[1] : ''; var rgx = /(\d+)(\d{3})/; while (rgx.test(numbersBeforePoint)) { numbersBeforePoint= numbersBeforePoint.replace(rgx, '$1' + ',' + '$2'); } return numbersBeforePoint+ numbersAfterPoint; } – Weslley Rufino de Lima Jul 11 '22 at 10:30
58

Short solution:

var n = 1234567890;
String(n).replace(/(.)(?=(\d{3})+$)/g,'$1,')
// "1,234,567,890"
Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54
48

All non-obsolete browsers (and even some obsolete ones) now support the ECMAScript® Internationalization API Specification (ECMA-402), which provides Intl.NumberFormat. You can use that for this:

const nFormat = new Intl.NumberFormat();
const count = 42000000;
console.log(nFormat.format(count)); // 42,000,000 in many locales, 42.000.000 in many other locales

if (typeof Intl === "undefined" || !Intl.NumberFormat) {
    console.log("This browser doesn't support Intl.NumberFormat");
} else {
    const nFormat = new Intl.NumberFormat();
    const count = 42000000;
    console.log(nFormat.format(count)); // 42,000,000 in many locales, 42.000.000 in many other locales
}
Shlomo
  • 120
  • 2
  • 8
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
28

Due to the bugs found by JasperV — good points! — I have rewritten my old code. I guess I only ever used this for positive values with two decimal places.

Depending on what you are trying to achieve, you may want rounding or not, so here are two versions split across that divide.

First up, with rounding.

I've introduced the toFixed() method as it better handles rounding to specific decimal places accurately and is well support. It does slow things down however.

This version still detaches the decimal, but using a different method than before. The w|0 part removes the decimal. For more information on that, this is a good answer. This then leaves the remaining integer, stores it in k and then subtracts it again from the original number, leaving the decimal by itself.

Also, if we're to take negative numbers into account, we need to while loop (skipping three digits) until we hit b. This has been calculated to be 1 when dealing with negative numbers to avoid putting something like -,100.00

The rest of the loop is the same as before.

function formatThousandsWithRounding(n, dp){
  var w = n.toFixed(dp), k = w|0, b = n < 0 ? 1 : 0,
      u = Math.abs(w-k), d = (''+u.toFixed(dp)).substr(2, dp),
      s = ''+k, i = s.length, r = '';
  while ( (i-=3) > b ) { r = ',' + s.substr(i, 3) + r; }
  return s.substr(0, i + 3) + r + (d ? '.'+d: '');
};

In the snippet below you can edit the numbers to test yourself.

function formatThousandsWithRounding(n, dp){
  var w = n.toFixed(dp), k = w|0, b = n < 0 ? 1 : 0,
      u = Math.abs(w-k), d = (''+u.toFixed(dp)).substr(2, dp),
      s = ''+k, i = s.length, r = '';
  while ( (i-=3) > b ) { r = ',' + s.substr(i, 3) + r; }
  return s.substr(0, i + 3) + r + (d ? '.'+d: '');
};

var dp;
var createInput = function(v){
  var inp = jQuery('<input class="input" />').val(v);
  var eql = jQuery('<span>&nbsp;=&nbsp;</span>');
  var out = jQuery('<div class="output" />').css('display', 'inline-block');
  var row = jQuery('<div class="row" />');
  row.append(inp).append(eql).append(out);
  inp.keyup(function(){
    out.text(formatThousandsWithRounding(Number(inp.val()), Number(dp.val())));
  });
  inp.keyup();
  jQuery('body').append(row);
  return inp;
};

jQuery(function(){
  var numbers = [
    0, 99.999, -1000, -1000000, 1000000.42, -1000000.57, -1000000.999
  ], inputs = $();
  dp = jQuery('#dp');
  for ( var i=0; i<numbers.length; i++ ) {
    inputs = inputs.add(createInput(numbers[i]));
  }
  dp.on('input change', function(){
    inputs.keyup();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="dp" type="range" min="0" max="5" step="1" value="2" title="number of decimal places?" />

Now the other version, without rounding.

This takes a different route and attempts to avoid mathematical calculation (as this can introduce rounding, or rounding errors). If you don't want rounding, then you are only dealing with things as a string i.e. 1000.999 converted to two decimal places will only ever be 1000.99 and not 1001.00.

This method avoids using .split() and RegExp() however, both of which are very slow in comparison. And whilst I learned something new from Michael's answer about toLocaleString, I also was surprised to learn that it is — by quite a way — the slowest method out of them all (at least in Firefox and Chrome; Mac OSX).

Using lastIndexOf() we find the possibly existent decimal point, and from there everything else is pretty much the same. Save for the padding with extra 0s where needed. This code is limited to 5 decimal places. Out of my test this was the faster method.

var formatThousandsNoRounding = function(n, dp){
  var e = '', s = e+n, l = s.length, b = n < 0 ? 1 : 0,
      i = s.lastIndexOf('.'), j = i == -1 ? l : i,
      r = e, d = s.substr(j+1, dp);
  while ( (j-=3) > b ) { r = ',' + s.substr(j, 3) + r; }
  return s.substr(0, j + 3) + r + 
    (dp ? '.' + d + ( d.length < dp ? 
        ('00000').substr(0, dp - d.length):e):e);
};

var formatThousandsNoRounding = function(n, dp){
  var e = '', s = e+n, l = s.length, b = n < 0 ? 1 : 0,
      i = s.lastIndexOf('.'), j = i == -1 ? l : i,
      r = e, d = s.substr(j+1, dp);
  while ( (j-=3) > b ) { r = ',' + s.substr(j, 3) + r; }
  return s.substr(0, j + 3) + r + 
   (dp ? '.' + d + ( d.length < dp ? 
     ('00000').substr(0, dp - d.length):e):e);
};

var dp;
var createInput = function(v){
  var inp = jQuery('<input class="input" />').val(v);
  var eql = jQuery('<span>&nbsp;=&nbsp;</span>');
  var out = jQuery('<div class="output" />').css('display', 'inline-block');
  var row = jQuery('<div class="row" />');
  row.append(inp).append(eql).append(out);
  inp.keyup(function(){
    out.text(formatThousandsNoRounding(Number(inp.val()), Number(dp.val())));
  });
  inp.keyup();
  jQuery('body').append(row);
  return inp;
};

jQuery(function(){
  var numbers = [
    0, 99.999, -1000, -1000000, 1000000.42, -1000000.57, -1000000.999
  ], inputs = $();
  dp = jQuery('#dp');
  for ( var i=0; i<numbers.length; i++ ) {
    inputs = inputs.add(createInput(numbers[i]));
  }
  dp.on('input change', function(){
    inputs.keyup();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="dp" type="range" min="0" max="5" step="1" value="2" title="number of decimal places?" />

I'll update with an in-page snippet demo shortly, but for now here is a fiddle:

https://jsfiddle.net/bv2ort0a/2/



Old Method

Why use RegExp for this? — don't use a hammer when a toothpick will do i.e. use string manipulation:

var formatThousands = function(n, dp){
  var s = ''+(Math.floor(n)), d = n % 1, i = s.length, r = '';
  while ( (i -= 3) > 0 ) { r = ',' + s.substr(i, 3) + r; }
  return s.substr(0, i + 3) + r + 
    (d ? '.' + Math.round(d * Math.pow(10, dp || 2)) : '');
};

walk through

formatThousands( 1000000.42 );

First strip off decimal:

s = '1000000', d = ~ 0.42

Work backwards from the end of the string:

',' + '000'
',' + '000' + ',000'

Finalise by adding the leftover prefix and the decimal suffix (with rounding to dp no. decimal points):

'1' + ',000,000' + '.42'

fiddlesticks

http://jsfiddle.net/XC3sS/

Community
  • 1
  • 1
Pebbl
  • 34,937
  • 6
  • 62
  • 64
  • 4
    There are 2 bugs in this one: When using a negative number it fails with the decimals: `-1000000.42`becomes `-1,000,001.-42` and a one is added because the `floor`method. And it has another decimal error: when I process `1000000.999` with `dp=2` it becomes `1,000,000.100`, so 3 decimals and I my number is not rounded – JasperV Apr 07 '16 at 07:18
  • 3
    @JasperV, Very good points... cheers for the heads up. Not spotted those problems in any of my previous use-cases. Should be fixed now however. – Pebbl Apr 11 '16 at 22:11
10

Use the Number function toFixed and this function to add the commas.

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;
}
n = 10000;
r = n.toFixed(2); //10000.00

addCommas(r); // 10,000.00

http://www.mredkj.com/javascript/numberFormat.html

John Giotta
  • 16,432
  • 7
  • 52
  • 82
6

You may want to consider using toLocaleString()

Working Example:

const number = 1234567890.123;

console.log(number.toLocaleString('en-US')); // US format

console.log(number.toLocaleString('en-IN')); // Indian format

Tested in Chrome v60 and v88

Source: Number.prototype.toLocaleString() | MDN

Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
  • 2
    This is INCORRECT. The limit on (significant) digits comes from providing an options object into the .toLocaleString(locale_id, options) method. Like so: `toLocaleString(ANY_LOCALE_ID, { maximumSignificantDigits: 3 })` – Youp Bernoulli Jan 28 '21 at 10:39
  • 2
    @BernoulliIT thanks for bringing this up, I have updated my answer above – Rahul Desai Jan 28 '21 at 17:34
  • I don't see a correcting update of the answer!? This answer absolutely is the most straightforward and elegant solution to OP's question. – Youp Bernoulli Jan 29 '21 at 21:06
  • @BernoulliIT what do you mean `don't see a correcting update of the answer`? Have you tried clearing your browser cache? – Rahul Desai Jan 29 '21 at 22:28
  • You are right, I had in mind that OP's question was about limiting the number of digits (which was where I was looking for when finding this post) but that's not really the case. It got mixed up in my mind – Youp Bernoulli Feb 01 '21 at 09:38
5

I think with this jQuery-numberformatter you could solve your problem.

Of course, this is assuming that you don't have problem with using jQuery in your project. Please notice that the functionality is tied to the blur event.

$("#salary").blur(function(){
      $(this).parseNumber({format:"#,###.00", locale:"us"});
      $(this).formatNumber({format:"#,###.00", locale:"us"});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<script src="https://cdn.jsdelivr.net/gh/timdown/jshashtable/hashtable.js"></script>

<script src="https://cdn.jsdelivr.net/gh/hardhub/jquery-numberformatter/src/jquery.numberformatter.js"></script>

<input type="text" id="salary">
Cacho Santa
  • 6,846
  • 6
  • 41
  • 73
  • 1
    Google Code [was shut](https://opensource.googleblog.com/2015/03/farewell-to-google-code.html) [down on 2016-01-15](https://en.wikipedia.org/wiki/Google_Developers#Google_Code). You may want to update the broken link, ***"404. That's an error."*** (many projects on Google Code have been moved to [GitHub](http://en.wikipedia.org/wiki/GitHub)). – Peter Mortensen Oct 29 '17 at 13:53
  • thank you @PeterMortensen! updated the link! – Cacho Santa Feb 06 '18 at 04:55
  • why the downvote? care to explain? – Cacho Santa May 18 '18 at 16:57
  • updated with the code snippet to make it simpler to view the results and the script on the works. – Cacho Santa Feb 25 '19 at 00:03
4

function numberWithCommas(x) {
  x=String(x).toString();
  var afterPoint = '';
  if(x.indexOf('.') > 0)
     afterPoint = x.substring(x.indexOf('.'),x.length);
  x = Math.floor(x);
  x=x.toString();
  var lastThree = x.substring(x.length-3);
  var otherNumbers = x.substring(0,x.length-3);
  if(otherNumbers != '')
      lastThree = ',' + lastThree;
  return otherNumbers.replace(/\B(?=(\d{2})+(?!\d))/g, ",") + lastThree + afterPoint;
}

console.log(numberWithCommas(100000));
console.log(numberWithCommas(10000000));

Output

1,00,000
1,00,00,000

Michael
  • 8,362
  • 6
  • 61
  • 88
Ashish Gupta
  • 1,153
  • 12
  • 14
4

This is an article about your problem. Adding a thousands-seperator is not built in to JavaScript, so you'll have to write your own function like this (example taken from the linked page):

function addSeperator(nStr){
  nStr += '';
  x = nStr.split('.');
  x1 = x[0];
  x2 = x.length > 1 ? '.' + x[1] : '';
  var rgx = /(\d+)(\d{3})/;
  while (rgx.test(x1)) {
    x1 = x1.replace(rgx, '$1' + ',' + '$2');
  }
  return x1 + x2;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
oezi
  • 51,017
  • 10
  • 98
  • 115
2

Or you could use the sugar.js library, and the format method:

format( place = 0 , thousands = ',' , decimal = '.' ) Formats the number to a readable string. If place is undefined, will automatically determine the place. thousands is the character used for the thousands separator. decimal is the character used for the decimal point.

Examples:

(56782).format() > "56,782"
(56782).format(2) > "56,782.00"
(4388.43).format(2, ' ') > "4 388.43"
(4388.43).format(3, '.', ',') > "4.388,430"
andersh
  • 8,105
  • 6
  • 39
  • 30
2

Let me also throw my solution in here. I've commented each line for ease of reading and also provided some examples, so it may look big.

function format(number) {

    var decimalSeparator = ".";
    var thousandSeparator = ",";

    // make sure we have a string
    var result = String(number);

    // split the number in the integer and decimals, if any
    var parts = result.split(decimalSeparator);

    // if we don't have decimals, add .00
    if (!parts[1]) {
      parts[1] = "00";
    }
  
    // reverse the string (1719 becomes 9171)
    result = parts[0].split("").reverse().join("");

    // add thousand separator each 3 characters, except at the end of the string
    result = result.replace(/(\d{3}(?!$))/g, "$1" + thousandSeparator);

    // reverse back the integer and replace the original integer
    parts[0] = result.split("").reverse().join("");

    // recombine integer with decimals
    return parts.join(decimalSeparator);
}

document.write("10 => " + format(10) + "<br/>");
document.write("100 => " + format(100) + "<br/>");
document.write("1000 => " + format(1000) + "<br/>");
document.write("10000 => " + format(10000) + "<br/>");
document.write("100000 => " + format(100000) + "<br/>");
document.write("100000.22 => " + format(100000.22) + "<br/>");
Nicu Surdu
  • 8,172
  • 9
  • 68
  • 108
1

This will get you your comma seperated values as well as add the fixed notation to the end.

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

Source

clamchoda
  • 4,411
  • 2
  • 36
  • 74
0

This is about 3 times faster version of the accepted answer. It doesn't create array and avoids object creation and string concatenation for whole numbers at the end. This might be useful if you render lots of values e.g. in a table.

function addThousandSeparators(number) {
    var whole, fraction
    var decIndex = number.lastIndexOf('.')
    if (decIndex > 0) {
        whole = number.substr(0, decIndex)
        fraction = number.substr(decIndex)
    } else {
        whole = number
    }
    var rgx = /(\d+)(\d{3})/
    while (rgx.test(whole)) {
        whole = whole.replace(rgx, '$1' + ',' + '$2')
    }
    return fraction ? whole + fraction : whole
}
petrsyn
  • 5,054
  • 3
  • 45
  • 48
0
 function formatNumber1(number) {
  var comma = ',',
      string = Math.max(0, number).toFixed(0),
      length = string.length,
      end = /^\d{4,}$/.test(string) ? length % 3 : 0;
  return (end ? string.slice(0, end) + comma : '') + string.slice(end).replace(/(\d{3})(?=\d)/g, '$1' + comma);
 }

 function formatNumber2(number) {
  return Math.max(0, number).toFixed(0).replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
 }

Source: http://jsperf.com/number-format

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Adnan
  • 25,882
  • 18
  • 81
  • 110
0

If you're using jQuery, you could use the format or number format plugins.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
-1
                function formatThousands(n,dp,f) {
                    // dp - decimal places
                    // f - format >> 'us', 'eu'
                    if (n == 0) {
                        if(f == 'eu') {
                            return "0," + "0".repeat(dp);   
                        }
                        return "0." + "0".repeat(dp);
                    }

                    /* round to 2 decimal places */
                    //n = Math.round( n * 100 ) / 100;
                    var s = ''+(Math.floor(n)), d = n % 1, i = s.length, r = '';
                    while ( (i -= 3) > 0 ) { r = ',' + s.substr(i, 3) + r; }
                    var a = s.substr(0, i + 3) + r + (d ? '.' + Math.round((d+1) * Math.pow(10,dp)).toString().substr(1,dp) : '');
                    /* change format from 20,000.00 to 20.000,00 */
                    if (f == 'eu') {
                        var b = a.toString().replace(".", "#");
                        b = b.replace(",", ".");
                        return b.replace("#", ",");
                    }                   
                    return a;
                }
  • 2
    WHat's different about this answer compared to the other answers on the question? Can you elaborate the meaning of the code only answers? – Akin Okegbile Jul 05 '19 at 23:27