How to format numbers as currency strings

Asked 2023-09-20 20:30:16 View 208,833

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"

How can I 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. - anyone
  • @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 - anyone
  • @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 ? - anyone
  • 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/… - anyone
  • you can use this Numeral.js javascript library to convert your numbers to dollars. (numeraljs.com) for reference. - anyone

Answers

Intl.NumberFormat

JavaScript has a number formatter (part of the Internationalization API).

// Create our number formatter.
const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',

  // These options are needed to round to whole numbers if that's what you want.
  //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
  //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
});

console.log(formatter.format(2500)); /* $2,500.00 */

Use undefined in place of the first argument ('en-US' in the example) to use the system locale (the user locale in case the code is running in a browser). Further explanation of the locale code.

Here's a list of the currency codes.

Intl.NumberFormat vs Number.prototype.toLocaleString

A final note comparing this to the older .toLocaleString. They both offer essentially the same functionality. However, toLocaleString in its older incarnations (pre-Intl) does not actually support locales: it uses the system locale. So when debugging old browsers, be sure that you're using the correct version (MDN suggests to check for the existence of Intl). There isn't any need to worry about this at all if you don't care about old browsers or just use the shim.

Also, the performance of both is the same for a single item, but if you have a lot of numbers to format, using Intl.NumberFormat is ~70 times faster. Therefore, it's usually best to use Intl.NumberFormat and instantiate only once per page load. Anyway, here's the equivalent usage of toLocaleString:

console.log((2500).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD',
})); /* $2,500.00 */

Some notes on browser support and Node.js

  • Browser support is no longer an issue nowadays with 98% support globally, 99% in the US and 99+% in the EU
  • There is a shim to support it on fossilized browsers (like Internet Explorer 8), should you really need to
  • Node.js before v13 only supports en-US out of the box. One solution is to install full-icu, see here for more information
  • Have a look at CanIUse for more information

Answered   2023-09-20 20:30:16

  • Pretty sure a quite high % of browsers now support this. This should be upvoted much more. - anyone
  • This is a great answer and I have it working with a dynamic currency value so if use is in Europe then it changes to EUR and shows the euro sign. Works a treat! - anyone
  • Works great in React Native as well! - anyone
  • It's 2018 and this is basically supported everywhere. This should be the correct answer. - anyone
  • Support as far back as Internet Explorer 11 (IE 11), with all major browsers supporting as well. - anyone

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>

Answered   2023-09-20 20:30:16

  • 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. - anyone
  • Not sure why people think this code is beautiful. It is indecipherable. It seems to work nicely, but it is not beautiful. - anyone
  • 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! - anyone
  • "poetry"? More like obscurity. This isn't code golf; use a little white space. Proper var names wouldn't hurt, either. - anyone
  • Any fool can write code that a computer can understand. Good programmers write code that humans can understand - anyone

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"

DEMO: http://jsfiddle.net/hAfMM/9571/


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/

Answered   2023-09-20 20:30:16

  • I actually went a step further: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"). - anyone
  • 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," - anyone
  • @Abbas Yeah, replace \. with $ (end of line), i.e. this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,"). - anyone
  • @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". - anyone
  • @JuliendePrabère Please give an example of a long number which doesn't work with this approach. - anyone

Take a look at the JavaScript Number object and see if it can help you.

  • toLocaleString() will format a number using location specific thousands separator.
  • toFixed() will round the number to a specific number of decimal places.

To use these at the same time the value must have its type changed back to a number because they both output a string.

Example:

Number((someNumber).toFixed(1)).toLocaleString()

EDIT

One can just use toLocaleString directly and its not necessary to recast to a number:

someNumber.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});

Multiple numbers

If you need to frequently format numbers similarly you can create a specific object for reuse. Like for German (Switzerland):

const money = new Intl.NumberFormat('de-CH',
  { style:'currency', currency: 'CHF' });
const percent = new Intl.NumberFormat('de-CH',
  { style:'percent', maximumFractionDigits: 1, signDisplay: "always"});

which than can be used as:

money.format(1234.50); // output CHF 1'234.50
percent.format(0.083);  // output +8.3%

Pretty nifty.

Answered   2023-09-20 20:30:16

  • Thanks! Based on this idea I was able to make one that is short and simple enough! (and localized) Excellent. - anyone
  • Actually You can. i.e. for dollars: '$'+(value + 0.001).toLocaleString().slice(0,-1) - anyone
  • Looks like it'd be great, but there is little browser support at the moment - anyone
  • Care should be taken that there is an old version of toLocaleString that uses the system locale, and a new (incompatible) one that comes from ECMAScript Intl API. Explained here. This answer seems to be intended for the old version. - anyone
  • Not sure why this is so highly voted, but this doesn't do what OP is asking for. For example, 10000 would turn into "10,000" and not "10,000.00" which is the desired behavior for currency formatting. - anyone

Below is the Patrick Desjardins (alias Daok) code with a bit of comments added and some minor changes:

/*
decimal_sep: character used as decimal separator, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{
   var n = this,
   c = isNaN(decimals) ? 2 : Math.abs(decimals), // If decimal is zero we must take it. It means the user does not want to show any decimal
   d = decimal_sep || '.', // If no decimal separator is passed, we use the dot as default decimal separator (we MUST use a decimal separator)

   /*
   According to [https://stackoverflow.com/questions/411352/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
   the fastest way to check for not defined parameter is to use typeof value === 'undefined'
   rather than doing value === undefined.
   */
   t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, // If you don't want to use a thousands separator you can pass empty string as thousands_sep value

   sign = (n < 0) ? '-' : '',

   // Extracting the absolute value of the integer part of the number and converting to string
   i = parseInt(n = Math.abs(n).toFixed(c)) + '',

   j = ((j = i.length) > 3) ? j % 3 : 0;
   return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
}

And here some tests:

// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());

// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));

The minor changes are:

  1. moved a bit the Math.abs(decimals) to be done only when is not NaN.

  2. decimal_sep can not be empty string any more (a some sort of decimal separator is a must)

  3. we use typeof thousands_sep === 'undefined' as suggested in How best to determine if an argument is not sent to the JavaScript function

  4. (+n || 0) is not needed because this is a Number object

JSFiddle

Answered   2023-09-20 20:30:16

  • You may want to use '10' as the radix in parseInt. Otherwise, any number that starts with '0' will use octal numbering. - anyone
  • @sohtimsso1970: sorry for the late response, but could you explain some more? I don't see where a number could be interpreted as octal. The parseInt is called on the absolute value of the INTEGER part of the number. The INTEGER part can not start with ZERO unless it's just a ZERO! And parseInt(0) === 0 either octal or decimal. - anyone
  • try, for example: parseInt("016") ... returns 14, as parseInt assumes it's octal encoded, when the string begins with a zero. - anyone
  • @Tracker1: I understood that a number starting with 0 is considered octal by parseInt. But in this code is IMPOSSIBLE for parseInt to receive 016 as input (or any other octal formatted value), because the argument passed to parseInt is 1st processed by Math.abs function. So there is no way for parseInt to receive a number that starts with zero unless it's just a zero or 0.nn (where nn are decimals). But both 0 and 0.nn strings would be converted by parseInt into a plain ZERO as suppsed to be. - anyone
  • This function are incorrect: > (2030).toMoney(0, '.', ' '); < "2 03 0" - anyone

If amount is a number, say -123, then

amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });

will produce the string "-$123.00".

Here's a complete working example.

Answered   2023-09-20 20:30:16

  • This answer was almost there for me, but I needed it to be rounded to the nearest penny. This is what I used amount.toLocaleString('en-GB', { style: 'currency', currency: 'GBP', maximumFractionDigits: 2 }); - anyone
  • Doesn't seem to work in Safari. It just returns the number as a String without any formatting. - anyone
  • The MDN Documentation for anyone who would like to see the full set of options. - anyone
  • If for some reason you don't want cents, you can change decimal precision with: minimumFractionDigits: 0 - anyone
  • @Horacio / Nico - See earlier answer: stackoverflow.com/a/18994850/782034 - anyone

accounting.js is a tiny JavaScript library for number, money and currency formatting.

Answered   2023-09-20 20:30:16

  • ... just remember to pass a currency symbol otherwise it errors out in IE7 and IE8, IE9 is fine either way - anyone
  • Looks like the IE7/IE8 bug is fixed. - anyone
  • This is a great library, being able to pass the currency symbol is also a good idea, since all the currency details are contained in the single function call/settings - anyone
  • I like the fact that you can do the reverse--pass a formatted currency string and get the numeric value. - anyone
  • accounting.js doesn't seem maintained lately. One fork with recent changes is github.com/nashdot/accounting-js - anyone

Here's the best JavaScript money formatter I've seen:

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
    var n = this,
        decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
        decSeparator = decSeparator == undefined ? "." : decSeparator,
        thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;
    return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};

It was reformatted and borrowed from here: How to format numbers as currency strings

You'll have to supply your own currency designator (you used $ above).

Call it like this (although note that the arguments default to 2, comma, and period, so you don't need to supply any arguments if that's your preference):

var myMoney = 3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2, ',', '.'); // "$3,543.76"

Answered   2023-09-20 20:30:16

  • watch out for globals sign, i, j - anyone
  • @hacklikecrack, all variables are local; they're in the var statement. - anyone
  • sorry, yes, though you're redeclaring arguments. Indentation! ;) - anyone
  • Horrible use of variable names! - anyone

Here's another attempt, just for fun:

function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    return "$" + p[0].split("").reverse().reduce(function(acc, num, i, orig) {
        return num + (num != "-" && i && !(i % 3) ? "," : "") + acc;
    }, "") + "." + p[1];
}

And some tests:

formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"
formatDollar(-1345) // "$-1,345.00
formatDollar(-3) // "$-3.00"

Answered   2023-09-20 20:30:16

  • poetry. brilliant. have you tried reduceRight() developer.mozilla.org/en/JavaScript/Reference/Global_Objects/… which should eliminate the reverse() ? - anyone
  • @Steve - You're right, but you'd need to do something like i = orig.length - i - 1 in the callback. Still, one less traversal of the array. - anyone
  • A not about compatability: The reduce method was introduced in Ecmascript 1.8, and is not supported in Internet Explorer 8 and below. - anyone
  • Like @Blaise said, this method will not work in IE 8 or below. - anyone
  • Not work with negative number - anyone

Works for all current browsers

Use toLocaleString to format a currency in its language-sensitive representation (using ISO 4217 currency codes).

(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})

Example South African Rand code snippets for avenmore:

console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00

Answered   2023-09-20 20:30:16

  • Because 'locales' and 'options' arguments are supported just by a very small number of browsers, like Chrome 24, IE11 and Opera 15. Firefox, Safari and older versions of others still don't support it. - anyone
  • Agreed, it's not fully supported across all browsers (yet), but it's still a solution. (And arguably the most valid solution, as its forward compatible with the non-supported browsers, and it's a documented feature of the Javascript api.) - anyone
  • I like this and am happy that it works with Indian digit grouping. - anyone
  • This is fully supported as of 2017 and should be the only correct answer - anyone
  • Latest and greatest :) FF69, Chrome76, etc. "R 2 500,00" is not what we use here, it should be "R 2,500.00", same as en-GB. - anyone

I think you want:

f.nettotal.value = "$" + showValue.toFixed(2);

Answered   2023-09-20 20:30:16

  • @ crush this works but it no longer carries the calculations onto the tax field? - anyone
  • Once you append a $ sign to it, it is no longer a number, but a string. - anyone
  • This option doesn't put a comma between the thousands. :-( - anyone
  • @crush, as a pedantic note, before the dollar sign is appended to the right side value, the .toFixed() function will return the number as a formatted string. So the concatenation in this case is string-to-string. - anyone

just use the native javascript Intl

you just use the options to format its value

const number = 1233445.5678
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(number));

mozilla documentation link

Answered   2023-09-20 20:30:16

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[0];
var decPart = (arParts.length > 1 ? arParts[1] : '');
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...

Answered   2023-09-20 20:30:16

  • 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. - anyone
  • 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. - anyone

Numeral.js - a JavaScript library for easy number formatting by @adamwdraper

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"

Answered   2023-09-20 20:30:16

  • The fork Numbro seems to get more love as Numeral.js seems abandoned: github.com/foretagsplatsen/numbro - anyone
  • Numeral.js is active again. - anyone
  • Im using this solution today. But when there are no decimal digits in the original number, its showing the ".00" anyway. Is there a format to allow 2 decimal numbers but that hides them when they aren't needed? - anyone

The following is concise, easy to understand, and doesn't rely on any overly complicated regular expressions.

function moneyFormat(price, sign = '$') {
  const pieces = parseFloat(price).toFixed(2).split('')
  let ii = pieces.length - 3
  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, ',')
  }
  return sign + pieces.join('')
}

console.log(
  moneyFormat(100),
  moneyFormat(1000),
  moneyFormat(10000.00),
  moneyFormat(1000000000000000000)
)

Here is a version with more options in the final output to allow formatting different currencies in different locality formats.

// higher order function that takes options then a price and will return the formatted price
const makeMoneyFormatter = ({
  sign = '$',
  delimiter = ',',
  decimal = '.',
  append = false,
  precision = 2,
  round = true,
  custom
} = {}) => value => {

  const e = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]

  value = round
    ? (Math.round(value * e[precision]) / e[precision])
    : parseFloat(value)

  const pieces = value
    .toFixed(precision)
    .replace('.', decimal)
    .split('')

  let ii = pieces.length - (precision ? precision + 1 : 0)

  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, delimiter)
  }

  if (typeof custom === 'function') {
    return custom({
      sign,
      float: value,
      value: pieces.join('')
    })
  }

  return append
    ? pieces.join('') + sign
    : sign + pieces.join('')
}

// create currency converters with the correct formatting options
const formatDollar = makeMoneyFormatter()
const formatPound = makeMoneyFormatter({
  sign: '£',
  precision: 0
})
const formatEuro = makeMoneyFormatter({
  sign: '€',
  delimiter: '.',
  decimal: ',',
  append: true
})

const customFormat = makeMoneyFormatter({
  round: false,
  custom: ({ value, float, sign }) => `SALE:$${value}USD`
})

console.log(
  formatPound(1000),
  formatDollar(10000.0066),
  formatEuro(100000.001),
  customFormat(999999.555)
)

Answered   2023-09-20 20:30:16

  • Great code snippet, thank you. However, be careful, as it will not work on IE because default parameters are not supported, and "const" and "let" not supported in <IE11. Ue this to fix: + moneyFormat: function (price, sign) { + if (!sign) sign = '$'; + pieces = parseFloat(price).toFixed(2).split('') + var ii = pieces.length - 3 - anyone
  • No worries @CharlieDalsass. I would recommend using babel to compile it down to ES5 for production code. - anyone
  • But how to do Euro currency? 1.000,00 Euro? - anyone
  • @YumYumYum I added a full example with more formatting options to allow for more flexibility. - anyone

I use the library Globalize (from Microsoft):

It's a great project to localize numbers, currencies and dates and to have them automatically formatted the right way according to the user locale! ...and despite it should be a jQuery extension, it's currently a 100% independent library. I suggest you all to try it out! :)

Answered   2023-09-20 20:30:16

  • Wow, why is this not upvoted more? Big standardized library for all sorts of formatting. Industry-standard formatting parameters with correct globalization. Great answer!! - anyone
  • It is still considered alpha stage, so use cautiously, but great find. - anyone
  • No longer in alpha (or beta). This seems to be very useful while we wait for Safari to meet the new standard and for IE < 11 to die. - anyone

A shorter method (for inserting space, comma or point) with a regular expression:

    Number.prototype.toCurrencyString = function(){
        return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g, '$1 ');
    }

    n = 12345678.9;
    alert(n.toCurrencyString());

Answered   2023-09-20 20:30:16

  • This is amazing! Should be the best answers,! - anyone
  • This really helpful, simple and awesome - anyone

javascript-number-formatter (formerly at Google Code)

  • Short, fast, flexible yet stand-alone.
  • Accept standard number formatting like #,##0.00 or with negation -000.####.
  • Accept any country format like # ##0,00, #,###.##, #'###.## or any type of non-numbering symbol.
  • Accept any numbers of digit grouping. #,##,#0.000 or #,###0.## are all valid.
  • Accept any redundant/foolproof formatting. ##,###,##.# or 0#,#00#.###0# are all OK.
  • Auto number rounding.
  • Simple interface, just supply mask & value like this: format( "0.0000", 3.141592).
  • Include a prefix & suffix with the mask

(excerpt from its README)

Answered   2023-09-20 20:30:16

Please try the below code

"250000".replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');

Ans: 250,000

Enter image description here

Answered   2023-09-20 20:30:16

The main part is inserting the thousand-separators, and that could be done like this:

<script type="text/javascript">
  function ins1000Sep(val) {
    val = val.split(".");
    val[0] = val[0].split("").reverse().join("");
    val[0] = val[0].replace(/(\d{3})/g, "$1,");
    val[0] = val[0].split("").reverse().join("");
    val[0] = val[0].indexOf(",") == 0 ? val[0].substring(1) : val[0];
    return val.join(".");
  }

  function rem1000Sep(val) {
    return val.replace(/,/g, "");
  }

  function formatNum(val) {
    val = Math.round(val*100)/100;
    val = ("" + val).indexOf(".") > -1 ? val + "00" : val + ".00";
    var dec = val.indexOf(".");
    return dec == val.length-3 || dec == 0 ? val : val.substring(0, dec+3);
  }
</script>

<button onclick="alert(ins1000Sep(formatNum(12313231)));">

Answered   2023-09-20 20:30:16

  • I get wrong number output while entering negative values to ins1000Sep(). - anyone

+1 to Jonathan M for providing the original method. Since this is explicitly a currency formatter, I went ahead and added the currency symbol (defaults to '$') to the output, and added a default comma as the thousands separator. If you don't actually want a currency symbol (or thousands separator), just use "" (empty string) as your argument for it.

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
    // check the args and supply defaults:
    decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
    decSeparator = decSeparator == undefined ? "." : decSeparator;
    thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
    currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;

    var n = this,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;

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

Answered   2023-09-20 20:30:16

  • The first var is kinda weird, as those variables are already declared in the function declaration. Other than that, thanks! - anyone
  • You're right. That's an error I brought in from Jonathan M's original, where they're all chained as a single var expression. Those should be simple assignments. Fixing. - anyone
  • For that matter, I think this is probably prematurely optimized and should be refactored for readability. But my goal was to augment the OP's code, not fundamentally alter it. - anyone
  • It's not too bad – the +n || 0 is the only thing that seems a little odd (to me anyway). - anyone
  • this is a perfectly useful variable name. Converting it to n so you can save 3 characters at definition time may have been necessary in an era when RAM and bandwidth were counted in KB, but is merely obfuscatory in an era when the minifier will take care of all that before it ever hits production. The other clever micro-optimizations are at least debatable. - anyone

There is a JavaScript port of the PHP function "number_format".

I find it very useful as it is easy to use and recognisable for PHP developers.

function number_format (number, decimals, dec_point, thousands_sep) {
    var n = number, prec = decimals;

    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };

    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec);
    // Fix for Internet Explorer parseFloat(0.55).toFixed(0) = 0;

    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;

    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;

        _[0] = s.slice(0,i + (n < 0)) +
               _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }

    var decPos = s.indexOf(dec);
    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
    }
    else if (prec >= 1 && decPos === -1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s;
}

(Comment block from the original, included below for examples & credit where due)

// Formats a number with grouped thousands
//
// version: 906.1806
// discuss at: http://phpjs.org/functions/number_format
// +   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)
// *     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'

Answered   2023-09-20 20:30:16

  • This is only one correct function: > number_format(2030, 0, '.', ' ') < '2 030' Great ! Thanks - anyone

Patrick Desjardins' answer looks good, but I prefer my JavaScript code simple. Here's a function I just wrote to take a number in and return it in currency format (minus the dollar sign):

// Format numbers to two decimals with commas
function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    var chars = p[0].split("").reverse();
    var newstr = '';
    var count = 0;
    for (x in chars) {
        count++;
        if(count%3 == 1 && count != 1) {
            newstr = chars[x] + ',' + newstr;
        } else {
            newstr = chars[x] + newstr;
        }
    }
    return newstr + "." + p[1];
}

Answered   2023-09-20 20:30:16

  • I needed something to work in both the browser and in an old version of Node. This worked perfectly. Thanks - anyone

There is a built-in function, toFixed, in JavaScript:

var num = new Number(349);
document.write("$" + num.toFixed(2));

Answered   2023-09-20 20:30:16

  • This answer looks redundant. Crush's answer already mentinoed toFixed() - anyone
  • toFixed() is a function of the Number object and won't work on var num if it was a String, so the additional context helped me. - anyone
function CurrencyFormatted(amount)
{
    var i = parseFloat(amount);
    if(isNaN(i)) { i = 0.00; }
    var minus = '';
    if(i < 0) { minus = '-'; }
    i = Math.abs(i);
    i = parseInt((i + .005) * 100);
    i = i / 100;
    s = new String(i);
    if(s.indexOf('.') < 0) { s += '.00'; }
    if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
    s = minus + s;
    return s;
}

From WillMaster.

Answered   2023-09-20 20:30:16

I suggest the NumberFormat class from Google Visualization API.

You can do something like this:

var formatter = new google.visualization.NumberFormat({
    prefix: '$',
    pattern: '#,###,###.##'
});

formatter.formatValue(1000000); // $ 1,000,000

Answered   2023-09-20 20:30:16

As usually, there are multiple ways of doing the same thing, but I would avoid using Number.prototype.toLocaleString since it can return different values based on the user settings.

I also don't recommend extending the Number.prototype - extending native objects prototypes is a bad practice since it can cause conflicts with other people code (e.g. libraries/frameworks/plugins) and may not be compatible with future JavaScript implementations/versions.

I believe that regular expressions are the best approach for the problem, here is my implementation:

/**
 * Converts number into currency format
 * @param {number} number    Number that should be converted.
 * @param {string} [decimalSeparator]    Decimal separator, defaults to '.'.
 * @param {string} [thousandsSeparator]    Thousands separator, defaults to ','.
 * @param {int} [nDecimalDigits]    Number of decimal digits, defaults to `2`.
 * @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
 */
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
    //default values
    decimalSeparator = decimalSeparator || '.';
    thousandsSeparator = thousandsSeparator || ',';
    nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;

    var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
        parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]

    if(parts){ //number >= 1000 || number <= -1000
        return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
    }else{
        return fixed.replace('.', decimalSeparator);
    }
}

Answered   2023-09-20 20:30:16

  • The point of toLocaleString is that it does adjust with the user's settings. - anyone

This might be a little late, but here's a method I just worked up for a coworker to add a locale-aware .toCurrencyString() function to all numbers. The internalization is for number grouping only, not the currency sign - if you're outputting dollars, use "$" as supplied, because $123 4567 in Japan or China is the same number of USD as $1,234,567 is in the US. If you're outputting euro, etc., then change the currency sign from "$".

Declare this anywhere in your HTML <head> section or wherever necessary, just before you need to use it:

  Number.prototype.toCurrencyString = function(prefix, suffix) {
    if (typeof prefix === 'undefined') { prefix = '$'; }
    if (typeof suffix === 'undefined') { suffix = ''; }
    var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
    return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
  }

Then you're done! Use (number).toCurrencyString() anywhere you need to output the number as currency.

var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"

Answered   2023-09-20 20:30:16

Number(value)
        .toFixed(2)
        .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")

Answered   2023-09-20 20:30:16

  • An explanation would be in order. For example, how can it be so simple and not covered by any of the previous more than 50 answers over 9 years (at the time)? - anyone

Here are some solutions and all pass the test suite. The test suite and benchmark are included. If you want copy and paste to test, try this gist.

Method 0 (RegExp)

It is based on VisioN's answer, but it fixes if there isn't a decimal point.

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');
        a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
        return a.join('.');
    }
}

Method 1

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.'),
            // Skip the '-' sign
            head = Number(this < 0);

        // Skip the digits that's before the first thousands separator
        head += (a[0].length - head) % 3 || 3;

        a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
        return a.join('.');
    };
}

Method 2 (Split to Array)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');

        a[0] = a[0]
            .split('').reverse().join('')
            .replace(/\d{3}(?=\d)/g, '$&,')
            .split('').reverse().join('');

        return a.join('.');
    };
}

Method 3 (Loop)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('');
        a.push('.');

        var i = a.indexOf('.') - 3;
        while (i > 0 && a[i-1] !== '-') {
            a.splice(i, 0, ',');
            i -= 3;
        }

        a.pop();
        return a.join('');
    };
}

Usage Example

console.log('======== Demo ========')
console.log(
    (1234567).format(0),
    (1234.56).format(2),
    (-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
    n = (n * 10) + (i % 10)/100;
    console.log(n.format(2), (-n).format(2));
}

Separator

If we want custom a thousands separator or decimal separator, use replace():

123456.78.format(2).replace(',', ' ').replace('.', ' ');

Test suite

function assertEqual(a, b) {
    if (a !== b) {
        throw a + ' !== ' + b;
    }
}

function test(format_function) {
    console.log(format_function);
    assertEqual('NaN', format_function.call(NaN, 0))
    assertEqual('Infinity', format_function.call(Infinity, 0))
    assertEqual('-Infinity', format_function.call(-Infinity, 0))

    assertEqual('0', format_function.call(0, 0))
    assertEqual('0.00', format_function.call(0, 2))
    assertEqual('1', format_function.call(1, 0))
    assertEqual('-1', format_function.call(-1, 0))

    // Decimal padding
    assertEqual('1.00', format_function.call(1, 2))
    assertEqual('-1.00', format_function.call(-1, 2))

    // Decimal rounding
    assertEqual('0.12', format_function.call(0.123456, 2))
    assertEqual('0.1235', format_function.call(0.123456, 4))
    assertEqual('-0.12', format_function.call(-0.123456, 2))
    assertEqual('-0.1235', format_function.call(-0.123456, 4))

    // Thousands separator
    assertEqual('1,234', format_function.call(1234.123456, 0))
    assertEqual('12,345', format_function.call(12345.123456, 0))
    assertEqual('123,456', format_function.call(123456.123456, 0))
    assertEqual('1,234,567', format_function.call(1234567.123456, 0))
    assertEqual('12,345,678', format_function.call(12345678.123456, 0))
    assertEqual('123,456,789', format_function.call(123456789.123456, 0))
    assertEqual('-1,234', format_function.call(-1234.123456, 0))
    assertEqual('-12,345', format_function.call(-12345.123456, 0))
    assertEqual('-123,456', format_function.call(-123456.123456, 0))
    assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
    assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
    assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))

    // Thousands separator and decimal
    assertEqual('1,234.12', format_function.call(1234.123456, 2))
    assertEqual('12,345.12', format_function.call(12345.123456, 2))
    assertEqual('123,456.12', format_function.call(123456.123456, 2))
    assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
    assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
    assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
    assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
    assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
    assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
    assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
    assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
    assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}

console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);

Benchmark

function benchmark(f) {
    var start = new Date().getTime();
    f();
    return new Date().getTime() - start;
}

function benchmark_format(f) {
    console.log(f);
    time = benchmark(function () {
        for (var i = 0; i < 100000; i++) {
            f.call(123456789, 0);
            f.call(123456789, 2);
        }
    });
    console.log(time.format(0) + 'ms');
}

// If not using async, the browser will stop responding while running.
// This will create a new thread to benchmark
async = [];
function next() {
    setTimeout(function () {
        f = async.shift();
        f && f();
        next();
    }, 10);
}

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();

Answered   2023-09-20 20:30:16

  • Improved from your method 2. change from var a = this.toFixed(precision).split('.'), to var multiplier = Math.pow( 10, precision + 1 ), wholeNumber = Math.floor( this * multiplier ); var a = Math.round( wholeNumber / 10 ) * 10 / multiplier; if (String(a).indexOf('.') < 1) { a += '.00'; } a = String(a).split('.'), Don't use toFixed because it is buggy. - anyone
  • console.log(parseFloat('4.835').toFixed(2)); > 4.83 console.log(parseFloat('54.835').toFixed(2)); > 54.84 console.log(parseFloat('454.835').toFixed(2)); > 454.83 console.log(parseFloat('8454.835').toFixed(2)); > 8454.83 all of these value's decimal should be .84 not .83 - anyone