Categories

# How to format numbers as currency strings

I would like to format a price in JavaScript. I’d like a function which takes a `float` as an argument and returns a `string` formatted like this:

``````"\$ 2,500.00"
``````

What’s the best way to do this?

• Please, to anyone reading this in the future, do not use float to store currency. You will loose precision and data. You should store it as a integer number of cents (or pennies etc.) and then convert prior to output.

Mar 4, 2012 at 13:35

• @user1308743 Float doesn’t store decimal places. It stores numbers using a value, base and offset. 0.01 is not actually representable. See: en.wikipedia.org/wiki/Floating_point#Accuracy_problems

Jun 10, 2012 at 11:11

• @user1308743: Imagine you represent a very big number (lets say you are a lucky guy and it is your bank account balance). Would you really want to loose money because of a precision deficiency ?

Aug 6, 2012 at 9:14

• So why hasn’t anyone suggested the following? (2500).toLocaleString(“en-GB”, {style: “currency”, currency: “GBP”, minimumFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Sep 25, 2013 at 1:41

• you can use this Numeral.js javascript library to convert your numbers to dollars. (numeraljs.com) for reference.

Sep 11, 2014 at 10:30

Ok, based on what you said, I’m using this:

``````var DecimalSeparator = Number("1.2").toLocaleString().substr(1,1);

var AmountWithCommas = Amount.toLocaleString();
var arParts = String(AmountWithCommas).split(DecimalSeparator);
var intPart = arParts;
var decPart = (arParts.length > 1 ? arParts : '');
decPart = (decPart + '00').substr(0,2);

return '£ ' + intPart + DecimalSeparator + decPart;
``````

I’m open to improvement suggestions (I’d prefer not to include YUI just to do this 🙂 )

I already know I should be detecting the “.” instead of just using it as the decimal separator…

• Note that your version doesn’t properly round to two decimal digits. For example, 3.706 would be formatted as “£ 3.70”, not as “£ 3.71” as it’s supposed to be.

Sep 30, 2008 at 23:33

• Yes, that’s OK in my particular case, since the amounts I’m working with already have at most 2 digits The reason I need to fix to 2 decimals is for amounts with no decimals or with only 1.

Oct 2, 2008 at 19:12

## Number.prototype.toFixed

This solution is compatible with every single major browser:

``````  const profits = 2489.8237;

profits.toFixed(3) // Returns 2489.824 (rounds up)
profits.toFixed(2) // Returns 2489.82
profits.toFixed(7) // Returns 2489.8237000 (pads the decimals)
``````

All you need is to add the currency symbol (e.g. `"\$" + profits.toFixed(2)`) and you will have your amount in dollars.

## Custom function

If you require the use of `,` between each digit, you can use this function:

``````function formatMoney(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;

return sign +
(j ? i.substr(0, j) + thouSep : "") +
i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "\$1" + thouSep) +
(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}

document.getElementById("b").addEventListener("click", event => {
document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});``````
``````<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>``````

Use it like so:

``````(123456789.12345).formatMoney(2, ".", ",");
``````

If you’re always going to use ‘.’ and ‘,’, you can leave them off your method call, and the method will default them for you.

``````(123456789.12345).formatMoney(2);
``````

If your culture has the two symbols flipped (i.e., Europeans) and you would like to use the defaults, just paste over the following two lines in the `formatMoney` method:

``````    d = d == undefined ? "," : d,
t = t == undefined ? "." : t,
``````

## Custom function (ES6)

If you can use modern ECMAScript syntax (i.e., through Babel), you can use this simpler function instead:

``````function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
try {
decimalCount = Math.abs(decimalCount);
decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

const negativeSign = amount < 0 ? "-" : "";

let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
let j = (i.length > 3) ? i.length % 3 : 0;

return
negativeSign +
(j ? i.substr(0, j) + thousands : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, "\$1" + thousands) +
(decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
} catch (e) {
console.log(e)
}
};

document.getElementById("b").addEventListener("click", event => {
document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});``````
``````<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>``````

• first of all, excellent, concise code. however, if you are american, you should change the defaults of `d` and `t` to be `.` and `,` respectively so that you don’t have to specify them every time. also, i recommend modifying the beginning of the `return` statement to read: `return s + '\$' + [rest]`, otherwise you will not get a dollar sign.

Jan 31, 2011 at 23:58

• Not sure why people think this code is beautiful. It is indecipherable. It seems to work nicely, but it is not beautiful.

– usr

Oct 24, 2012 at 16:28

• Is this formatMoney function copied from some minified JavaScript code somewhere? Can you not post the original? What do the variables c, d, i, j, n, s, and t stand for? Judging by the amount of upvotes and comments this post has I can assume this code has been copy pasted into production websites everywhere… Good luck maintaining the code if it has a bug some day!

Dec 17, 2012 at 20:41

• “poetry”? More like obscurity. This isn’t code golf; use a little white space. Proper var names wouldn’t hurt, either.

Dec 30, 2012 at 14:07

## Short and fast solution (works everywhere!)

``````(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '\$&,');  // 12,345.67
``````

The idea behind this solution is replacing matched sections with first match and comma, i.e. `'\$&,'`. The matching is done using lookahead approach. You may read the expression as “match a number if it is followed by a sequence of three number sets (one or more) and a dot”.

TESTS:

``````1        --> "1.00"
12       --> "12.00"
123      --> "123.00"
1234     --> "1,234.00"
12345    --> "12,345.00"
123456   --> "123,456.00"
1234567  --> "1,234,567.00"
12345.67 --> "12,345.67"
``````

## Extended short solution

You can also extend the prototype of `Number` object to add additional support of any number of decimals `[0 .. n]` and the size of number groups `[0 .. x]`:

``````/**
* Number.prototype.format(n, x)
*
* @param integer n: length of decimal
* @param integer x: length of sections
*/
Number.prototype.format = function(n, x) {
var re="\\d(?=(\\d{" + (x || 3) + '})+' + (n > 0 ? '\\.' : '\$') + ')';
return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '\$&,');
};

1234..format();           // "1,234"
12345..format(2);         // "12,345.00"
123456.7.format(3, 2);    // "12,34,56.700"
123456.789.format(2, 4);  // "12,3456.79"
``````

DEMO / TESTS: http://jsfiddle.net/hAfMM/435/

## Super extended short solution

In this super extended version you may set different delimiter types:

``````/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed   s: sections delimiter
* @param mixed   c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re="\\d(?=(\\d{" + (x || 3) + '})+' + (n > 0 ? '\\D' : '\$') + ')',
num = this.toFixed(Math.max(0, ~~n));

return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '\$&' + (s || ','));
};

12345678.9.format(2, 3, '.', ',');  // "12.345.678,90"
123456.789.format(4, 4, ' ', ':');  // "12 3456:7890"
12345678.9.format(0, 3, '-');       // "12-345-679"
``````

DEMO / TESTS: http://jsfiddle.net/hAfMM/612/

• I actually went a step further: `.replace(/(\d)(?=(\d{3})+(?:\.\d+)?\$)/g, "\$1,")`.

Mar 21, 2013 at 2:50

• CoffeeScript version with of VisioN & kalisjoshua regexp and way of specifying decimal place (so you can leave the default of 2 or specify 0 for no decimal): `Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?\$)/g, "\$1,"`

Jun 18, 2013 at 15:43

• @Abbas Yeah, replace `\.` with `\$` (end of line), i.e. `this.toFixed(0).replace(/(\d)(?=(\d{3})+\$)/g, "\$1,")`.

Aug 15, 2013 at 9:26

• @hanumant The regular grammar is a bit complicated here, so I suggest you to read the manuals about regular expressions first (e.g. at MDN). The idea behind it is replacing matched sections with first match and comma, i.e. `\$1,`. The matching is done using lookahead approach. You may read the expression as “match a number if it is followed by a sequence of three number sets (one or more) and a dot”.

Oct 22, 2013 at 15:08

• @JuliendePrabère Please give an example of a long number which doesn’t work with this approach.

Mar 25, 2014 at 10:53