How to format numbers as currency strings

2,452,853

Solution 1

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

Solution 2

Intl.NumberFormat

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

// Create our number formatter.
var 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)
});

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:

(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

Solution 3

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>

Solution 4

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/

Solution 5

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.

Share:
2,452,853
recursive9
Author by

recursive9

Founder of Crystal Gears Portfolio: - www.movertrends.com - www.friendshopper.com - www.digitalshow.com - www.translatorscorner.com - www.gigpay.com

Updated on July 08, 2022

Comments

  • recursive9
    recursive9 almost 2 years

    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?

    • recursive9
      recursive9 over 15 years
      Preferably, not necessarily. I just posted an answer that does, I think, based of people's suggestions
    • Philip Whitehouse
      Philip Whitehouse about 12 years
      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.
    • Kyle
      Kyle almost 12 years
      @PhilipWhitehouse what would cause loss of data of less than 2 decimal places?
    • Philip Whitehouse
      Philip Whitehouse almost 12 years
      @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
    • ereOn
      ereOn almost 12 years
      @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 ?
    • Ben Hull
      Ben Hull about 11 years
      @PhilipWhitehouse is right: it's definitely a bad idea to store money as floats. However, storing money as cents only works when you're dealing only in whole cents, which isn't precise enough for a lot of operations. We've recently switched to storing currencies as a 'Big Decimal', of 7 decimal places. You can use Javascript's toFixed(7) method to emulate this, though it returns a string by necessity. It does mean you can deal in familiar $xx.xx formats, though, without converting back from cents.
    • Nick Grealy
      Nick Grealy over 10 years
      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/…
    • Ben
      Ben over 9 years
      @NickG I am guessing because of it's pretty rubbish support from legacy browsers. But in an ideal world (where everyone has up to date browsers) this would be the best solution.
    • Aarthi Chandrasekaran
      Aarthi Chandrasekaran over 9 years
      you can use this Numeral.js javascript library to convert your numbers to dollars. (numeraljs.com) for reference.
    • einstein
      einstein over 9 years
      Don't forget the English language wrap negative currency amounts in parentthesis ($#,##0.00).
    • Testo Testini
      Testo Testini over 9 years
      @NickG I was enthusiast of your solution but does not work in IPad, Android and IE7, works only in Mozilla and Opera of what I checked
    • Nick Grealy
      Nick Grealy over 9 years
      @TestoTestini - thanks, fyi Mozilla have documented a compatibility table for browsers developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • cssyphus
      cssyphus over 9 years
      @TestoTestini (a)NickG See this jsFiddle: jsfiddle.net/v7tws309
    • Bergi
      Bergi about 9 years
      @RoccoTheTaco: Not sure what you're saying. The other question is older, has more upvotes, more answers, and a higher-voted answer. The (subjective) avg quality of the answers is similar. To be honest though, they best should be merged.
    • Bergi
      Bergi about 9 years
      There's nothing wrong with being generic, is it?
    • Curtis Yallop
      Curtis Yallop almost 9 years
      @PhilipWhitehouse While it is not good to store it as float, I believe it is ok to display currency in js as floats. As long as you don't perform calculations on it eg sum a column, etc. I store and manipulate the value in c# decimal and simply send it down to js as a float where it is displayed. If you type ".1" or ".61" into the console, it displays fine even though "1.03-.42" does not. Rudimentary test: for(var i = -200; i <= 200; ++i) console.log(i/100); I also send edited floats back up to my web server which should be ok: JSON.stringify(.1): "0.1".
    • Amir
      Amir about 7 years
      If you're reading this in >= 2017, this should be useful: link
    • aross
      aross almost 7 years
      @Amir, that's already in my answer
    • LogicDaemon
      LogicDaemon about 5 years
      @CurtisYallop only if showing value without currency, because english.stackexchange.com/a/11327/118419
    • Mike Aron
      Mike Aron over 3 years
      @NickGrealy Holy shittt. Dude i did not know this function. I wrote always my custom functions. Cooooool. THX
    • Nick Grealy
      Nick Grealy over 3 years
      Thanks @MikeAron, anytime. Give this a +1 to help others - stackoverflow.com/a/18994850/782034
    • Rajeev Jayaswal
      Rajeev Jayaswal over 3 years
      For INR conversion - use (4027775861.4).toLocaleString('en-IN', { maximumFractionDigits: 2, style: 'currency', currency: 'INR' }); // returns -> "₹4,02,77,75,861.40"
    • Peter Mortensen
      Peter Mortensen about 3 years
      @Philip Whitehouse: *lose precision (not loose precision). (Only a moderator can fix it - it is possible to raise a moderator flag.)
  • recursive9
    recursive9 over 15 years
    Too long, and i'd have to include YUI
  • recursive9
    recursive9 over 15 years
    Thanks! Based on this idea I was able to make one that is short and simple enough! (and localized) Excellent.
  • recursive9
    recursive9 over 15 years
    Sorry, no. That will remove extra decimal places, but it won't fix to 2 decimal positions. "25" will be "$ 25" with your code, not "$ 25.00"
  • Ates Goral
    Ates Goral over 15 years
    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.
  • recursive9
    recursive9 over 15 years
    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.
  • recursive9
    recursive9 over 15 years
    Still wrong! You're using toLocaleString, which can make the decimal separator "," instead of ".", and assuming it's "."
  • Ates Goral
    Ates Goral over 15 years
    This was a "minimalistic" approach to meet the original vague requirements that just gave "$ 2,500.00" as an example.
  • Ryan
    Ryan over 13 years
    If you always want to round up on 5 and down below 5, you cannot rely on toFixed() because of standard issues involved in representing floating point in binary. For example, try (1.005).toFixed(2).
  • Ricardo Gomes
    Ricardo Gomes over 13 years
    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.
  • Zhenya
    Zhenya over 12 years
    Thanks, this is great. Modified to work with user input strings instead (strips the string to numerics first in case they enter $1,500). String.prototype.formatMoney = function(c, d, t){ var n_dirty = this, n = n_dirty.replace(/[^\d.]/g,''), c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "." : d, t = t == undefined ? "," : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0; return s + (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) : ""); };
  • vector
    vector over 12 years
    ... just remember to pass a currency symbol otherwise it errors out in IE7 and IE8, IE9 is fine either way
  • sohtimsso1970
    sohtimsso1970 over 12 years
    You may want to use '10' as the radix in parseInt. Otherwise, any number that starts with '0' will use octal numbering.
  • sohtimsso1970
    sohtimsso1970 over 12 years
    You may want to use '10' as the radix in parseInt. Otherwise, any number that starts with '0' will use octal numbering.
  • Patrick Desjardins
    Patrick Desjardins over 12 years
    The default value of 0 to be octal is still there but deprecated. But yes you can add it if you want.
  • Nick Perkins
    Nick Perkins over 12 years
    My first reaction was "lol--too long, YUI sucks"...but upon reconsideration, it's not bad code, it's just very...complete. It checks whether the arg is actually a number ( not done by other posters, and the only part that requires YUI library ). It does rounding ( not done by all posters ). It has configurable separator, prefix, and suffix. Lastly, the code is commented, and uses no regex and no tricky one-liners. So...I am giving you a +1 to compensate for others -1...this code is not bad -- it could be adapted even if not using YUI.
  • Steve
    Steve over 12 years
    poetry. brilliant. have you tried reduceRight() developer.mozilla.org/en/JavaScript/Reference/Global_Objects‌​/… which should eliminate the reverse() ?
  • Wayne
    Wayne over 12 years
    @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.
  • Mat Schaffer
    Mat Schaffer over 12 years
    Looks like the IE7/IE8 bug is fixed.
  • Marco Demaio
    Marco Demaio over 12 years
    At YUI they must be sick, can't believe they wrote such piece of code.
  • Marco Demaio
    Marco Demaio over 12 years
    @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.
  • Rocco The Taco
    Rocco The Taco over 12 years
    @ crush this works but it no longer carries the calculations onto the tax field?
  • crush
    crush over 12 years
    Once you append a $ sign to it, it is no longer a number, but a string.
  • Tracker1
    Tracker1 about 12 years
    try, for example: parseInt("016") ... returns 14, as parseInt assumes it's octal encoded, when the string begins with a zero.
  • Marco Demaio
    Marco Demaio about 12 years
    @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.
  • Blaise
    Blaise about 12 years
    A not about compatability: The reduce method was introduced in Ecmascript 1.8, and is not supported in Internet Explorer 8 and below.
  • Ian Dunn
    Ian Dunn over 11 years
    This answer looks redundant. Crush's answer already mentinoed toFixed()
  • farinspace
    farinspace over 11 years
    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
  • usr
    usr over 11 years
    Not sure why people think this code is beautiful. It is indecipherable. It seems to work nicely, but it is not beautiful.
  • jao
    jao over 11 years
    please provide an example on how to use the function.
  • timborden
    timborden over 11 years
    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.
  • zuallauz
    zuallauz over 11 years
    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!
  • Nick Colgan
    Nick Colgan over 11 years
    This solution doesn't work very well. 1.155.formatMoney(2,'.',',) === '1.16', but 2.155.formatMoney(2,'.',',') === '2.15'
  • keithjgrant
    keithjgrant over 11 years
    "poetry"? More like obscurity. This isn't code golf; use a little white space. Proper var names wouldn't hurt, either.
  • kalisjoshua
    kalisjoshua about 11 years
    I actually went a step further: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,").
  • Rich Bradshaw
    Rich Bradshaw about 11 years
    The first var is kinda weird, as those variables are already declared in the function declaration. Other than that, thanks!
  • Eric Anderson
    Eric Anderson almost 11 years
    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,"
  • rsbarro
    rsbarro almost 11 years
    Like @Blaise said, this method will not work in IE 8 or below.
  • Abbas
    Abbas almost 11 years
    If we call toFixed(0), the commas disappear, any idea on getting it to work with this.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "$1,")?
  • Joseph Lennox
    Joseph Lennox almost 11 years
    The point of toLocaleString is that it does adjust with the user's settings.
  • VisioN
    VisioN almost 11 years
    @Abbas Yeah, replace \. with $ (end of line), i.e. this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,").
  • trejder
    trejder over 10 years
    Not mentioning, that d == undefined is used, while typeof(d) === 'undefined' should be in place.
  • pbarranis
    pbarranis over 10 years
    Wow, why is this not upvoted more? Big standardized library for all sorts of formatting. Industry-standard formatting parameters with correct globalization. Great answer!!
  • Wayne
    Wayne over 10 years
    Yes, that's of course correct. As noted in the answer itself, this is just for fun. Also, it should handle negative numbers just fine.
  • VisioN
    VisioN over 10 years
    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.
  • Micaël Félix
    Micaël Félix over 10 years
    @trejder why so? If you have silly programmers that define undefined as a variable with content you're good to go. Btw you don't need to (and so should not) use parenthesis for typeof.
  • trejder
    trejder over 10 years
    @MykaEyl Read about JS fundamentals before you say things, that are... a little bit wrong. A variable named undefined is defined by JS, not by some silly programmers and you should use parenthesis for typeof, because without it you'll be comparing it to that variable, named undefined. I don't present here my own thoughts, I just copied what is expressed in many SO answers and in many sources. Don't have time to find example right now, but you'll for sure find it, if you google a little bit more.
  • Nick Grealy
    Nick Grealy over 10 years
    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.)
  • XML
    XML over 10 years
    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.
  • XML
    XML over 10 years
    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.
  • Rich Bradshaw
    Rich Bradshaw over 10 years
    It's not too bad – the +n || 0 is the only thing that seems a little odd (to me anyway).
  • XML
    XML over 10 years
    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.
  • Rich Bradshaw
    Rich Bradshaw over 10 years
    True – didn't catch that one.
  • hanumant
    hanumant over 10 years
    Hi @VisioN, can you please explain the regex and importance of "$1,". I used the regex function but missed the $ in "$1,". So the result was incorrect. Will help me if you can explain. TIA.
  • VisioN
    VisioN over 10 years
    @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".
  • Zaptree
    Zaptree over 10 years
    Actually You can. i.e. for dollars: '$'+(value + 0.001).toLocaleString().slice(0,-1)
  • user2864740
    user2864740 over 10 years
    @trejder The parenthesis with the typeof make absolutely no difference to how the construct is parsed that form - typeof has the same precedence as a unary operator. Also the previous comment was saying that it's safe to rely that undefined evaluates to (void 0) as long as a "silly programmer" doesn't introduce a shadowing undefined local variable or rebind window.undefined. (I would consider that code the offender, not the code using undefined.)
  • trejder
    trejder over 10 years
    @user2864740 On second thought, I agree (of course!) on not using parenthesis (I had to be blind, when first time reading Myka Eyl's comment! :]). But I disagree on second part. The reason, why you should use typeof d === 'undefined' instead of d === undefined is, that with first approach you don't have to care about silly developers. Since world is overwhelmed by silly developers, we need to spend our time on actual coding, not of foreseeing silly developers' possible attempts to ruin our code, right? :]
  • user2864740
    user2864740 over 10 years
    @trejder I've never run into that problem. Any environment in which undefined has been redefined to a value other than (void 0) is an environment which I will not support. (In Python 2.x, True and False were just variables - e.g. True,False=False,True is permissible - but there was never any push to find a "safe" method.)
  • Luke Page
    Luke Page over 10 years
    this is just copied from a google search. The project hasn't been updated since 2011
  • hacklikecrack
    hacklikecrack over 10 years
    watch out for globals sign, i, j
  • Jonathan M
    Jonathan M over 10 years
    @hacklikecrack, all variables are local; they're in the var statement.
  • acorncom
    acorncom over 10 years
    Looks like it'd be great, but there is little browser support at the moment
  • Bob
    Bob over 10 years
    @trejder Since world is overwhelmed by silly developers, we need to spend our time on actual coding, not of foreseeing silly developers' possible attempts to ruin our code, right? => Following that line of thought, isn't typeof(d) === 'undefined' an attempt at foreseeing silly developers' possible attempts to ruin our code? If someone actually redefined undefined, I wouldn't trust them not to do something else to break your code.
  • hacklikecrack
    hacklikecrack about 10 years
    sorry, yes, though you're redeclaring arguments. Indentation! ;)
  • Michel Ayres
    Michel Ayres about 10 years
    @VisioN in the case of values for Brazilian standards (R$ 1.222.333,44) receiving (122233344). How should be done? I tried some changes in the fiddle without luck. Could you help me here? (or even add a format 3 in your example if there isn't too much to ask for). I know that the accepted answer cover this, but yours is great too
  • VisioN
    VisioN about 10 years
    @Michel Here is a super extended version, which supports different delimiter types: jsfiddle.net/hAfMM/610.
  • Julien de Prabère
    Julien de Prabère about 10 years
    @VisioN : Your short solution does not work for long number. It is necessary to replace the \. by a \b (for word boudarie) like I proposed on Jan 4'12 (see infra).
  • VisioN
    VisioN about 10 years
    @JuliendePrabère Please give an example of a long number which doesn't work with this approach.
  • Mike Causer
    Mike Causer about 10 years
    toCurrency('123456.7890') returns 123,456.7,890. IMHO, there should not be any commas in the decimal places. Other than that, looks good!
  • McGuireV10
    McGuireV10 almost 10 years
    @RobQuist He almost certainly meant flipped in comparison to what is in the code and not as an invitation to re-fight the Revolutionary War.
  • nikhil
    nikhil almost 10 years
    if someone want to undo the formatMoney back, here's the code: String.prototype.undoFormatMoney = function () { var tempVals; var val = this; var sign = ((val.split('$')[0]) == "-") ? "-" : "", val = val.split('$')[1]; tempVals = val.split(','); val = 0; var adjPlaces = 1; len1 = (tempVals.length) - 1; for (var i = len1, j = 0; i >= 0; i--, j++) { if (j > 0) { adjPlaces = j * 1000; } val = val + ((tempVals[i]) * adjPlaces); } return sign + "" + val; };
  • Neil Monroe
    Neil Monroe almost 10 years
    Safari definitely implements toLocale functions differently. The locale date formats also produce different output than every other major browser.
  • Neil Monroe
    Neil Monroe almost 10 years
    It is still considered alpha stage, so use cautiously, but great find.
  • Neil Monroe
    Neil Monroe almost 10 years
    I like the fact that you can do the reverse--pass a formatted currency string and get the numeric value.
  • Jared Beck
    Jared Beck over 9 years
  • Arsha
    Arsha over 9 years
    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.
  • Arsha
    Arsha over 9 years
    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
  • Nico
    Nico over 9 years
    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 });
  • hlascelles
    hlascelles over 9 years
    As previous commenters have mentioned, this is not just confusing, it is also wrong. It gives 49.65.formatMoney(1,'.',',') => 49.6
  • CookieCoder
    CookieCoder over 9 years
    I was using this, but got an error, so adding var myMoney = Number(myMoney).toFixed(2); adding Number() worked.
  • Betty Mock
    Betty Mock over 9 years
    Negative numbers worked fine for me. What I like about this is that there isn't very much code and it doesn't depend on a regex.
  • Kushal Shah
    Kushal Shah about 9 years
    Keep voting this one up as it's the best solution (if not the best answer).
  • Daniel Barbalace
    Daniel Barbalace about 9 years
    The above code does rounding to the number of digits you want. See the example and type in 1.237 in the input box.
  • Lance Anderson
    Lance Anderson about 9 years
    Doesn't seem to work in Safari. It just returns the number as a String without any formatting.
  • stackoverfloweth
    stackoverfloweth almost 9 years
    Not consistent across all browsers :/
  • Ken Palmer
    Ken Palmer almost 9 years
    Thanks for the heads-up @godmode. What browsers did you see problems with?
  • stackoverfloweth
    stackoverfloweth almost 9 years
    Safari 8.0.6 it wasn't trimming decimals, inserting "$", or adding commas
  • VisioN
    VisioN almost 9 years
    @Gyrocode.com Why $& approach didn't work for you?
  • Pier-Luc Gendreau
    Pier-Luc Gendreau almost 9 years
    Extra super extended version: jsfiddle.net/hAfMM/2269 Integrates currency symbol
  • Chase Sandmann
    Chase Sandmann almost 9 years
    Why didn't you just do (parseInt(p[0])).toLocaleString()?
  • Wayne
    Wayne almost 9 years
    Because that function can produce different results in different locales. That may very well be what you want, but it doesn't answer the specific formatting question directly. (Also, notice the date on the question/answers here.)
  • Bhargav Nanekalva
    Bhargav Nanekalva almost 9 years
    Asked for a JS solution!
  • Peter
    Peter almost 9 years
    I get wrong number output while entering negative values to ins1000Sep().
  • tggagne
    tggagne over 8 years
    Uptick the idea for using toLocaleString(), but downtick for the float. As was commented earlier, currency should never be stored in a float.
  • Ken Palmer
    Ken Palmer over 8 years
    Thanks @tggagne, you are correct. Bad oversight on my part.
  • Guy Schalnat
    Guy Schalnat over 8 years
    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.
  • Doug S
    Doug S over 8 years
    @acorncom Why do you say there is "little browser support"? The Number object has been around since Javascript 1.1. Please provide a reference that backs up your claim.
  • Clain Dsilva
    Clain Dsilva over 8 years
    Why this is not chosen as the best answer? Its has covered all possible options
  • Deji
    Deji over 8 years
    So many sourpusses in these comments. Wow, sure the code may not be the prettiest, but if you're worth your salt as a 'programmer', it is definitely not overly complicated or undecipherable, assuming you know how to read code, that is. And who ever maintains code they've copied and not created themselves anyway?
  • Andres Felipe
    Andres Felipe over 8 years
    ok awesome code, unfortunately i can't understand many things but it was very useful tks
  • aross
    aross over 8 years
    @Deji, coding style standards, naming things, code structuring, commenting and annotating be damned.
  • Deji
    Deji over 8 years
    @aross Is this question related to coding style standards, "naming things", code structuring, commenting and annoting? Is you vaguely mentioning any of those concepts providing any reasons that the particular code above is not a fitting answer? No...
  • aross
    aross over 8 years
    @Deji So you would even consider obfuscated code a good answer?
  • Deji
    Deji over 8 years
    @aross Depends on the question. That's what I think you're not getting here - the comments aren't for judging the quality of the code, but the quality of the ANSWER. I really shouldn't have to explain how answers to questions are usually judged for quality...
  • Kevin B
    Kevin B over 8 years
    Fortunately this is a community wiki, so any of you complaining about the code format/readability can just fix it on your own.
  • Anton P Robul
    Anton P Robul about 8 years
    This function is incorrect: > (2030).formatMoney(0, '.', ' '); < "2 03 0"
  • Anton P Robul
    Anton P Robul about 8 years
    This function are incorrect: > (2030).toMoney(0, '.', ' '); < "2 03 0"
  • Anton P Robul
    Anton P Robul about 8 years
    This is only one correct function: > number_format(2030, 0, '.', ' ') < '2 030' Great ! Thanks
  • RationalDev likes GoFundMonica
    RationalDev likes GoFundMonica about 8 years
    The fork Numbro seems to get more love as Numeral.js seems abandoned: github.com/foretagsplatsen/numbro
  • RationalDev likes GoFundMonica
    RationalDev likes GoFundMonica about 8 years
    accounting.js doesn't seem maintained lately. One fork with recent changes is github.com/nashdot/accounting-js
  • wosis
    wosis about 8 years
    Strange code, to my mind, ex. value gets re-assigned twice within the function, makes it very dificult to debug. With decimalPlaces = 0, the value is implicitly rounded by "toFixed", which is not indented in my case.
  • Liam
    Liam almost 8 years
  • VisioN
    VisioN almost 8 years
    @1111161171159459134 This is just a short and fast alternative to Math.floor(n). If you want to make it JSHint compliant, replace this bit accordingly.
  • MSC
    MSC almost 8 years
    I like this and am happy that it works with Indian digit grouping.
  • Connor Simpson
    Connor Simpson almost 8 years
    Small and simple. Thank you.
  • Admin
    Admin over 7 years
    How did such a terrible practice get 1K+ upvotes? Not to mention it was written pre-minified.
  • Trasiva
    Trasiva over 7 years
    Voting this one because it's a stupidly simple answer that works natively.
  • Mohammed Farooq
    Mohammed Farooq over 7 years
    Awesome code. Can it be possible to do reverse like un-format (12.345.678,90 to 12345678.9) similarly any currency format to normal number @VisioN
  • VisioN
    VisioN over 7 years
    @MohammedFarooq Sure, as easy as this: jsfiddle.net/hAfMM/3934.
  • Mohammed Farooq
    Mohammed Farooq over 7 years
    @VisioN- Thanks, But i dont need to pass (comma & dot ) as parameter. I need to return a number if i pass (12.345.678,90 to 12345678.9) or (12,345,678.90 to 12345678.9). EIther euro or standard format to normal number
  • VisioN
    VisioN over 7 years
    @MohammedFarooq To make this working the script should know what style your number is formatted with. It can't automatically detect if dot or comma is used as a separator for sections or a decimal part. Otherwise you have to use strict number format, so the parser may guess which character separates what part.
  • Matrix
    Matrix over 7 years
    How can I do to format "12514652" number? I can't call 12514652.format() like ruby... so?
  • Besat
    Besat over 7 years
    Thanks for your answer. I have a question though.How can I eliminate e+ from the number? for example 1000000000000000000000 now is formatting like: $ 1e+21 but I would like it to be like: $ 1,000,000,000,000,000,000,000.00
  • VisioN
    VisioN over 7 years
    @Besat That's a tricky one but we can use a nice workaround with a custom Number.prototype.toFixed method, that can implicitly transform numbers in scientific notation to their full length string representation. Please see the solution here: jsfiddle.net/hAfMM/4027.
  • Besat
    Besat over 7 years
    Wonderful! Thanks!
  • Faisal
    Faisal over 7 years
    how to make arr[i].price example, formatted to this? this code work great! @VisioN
  • Charlie Dalsass
    Charlie Dalsass over 7 years
    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
  • synthet1c
    synthet1c over 7 years
    No worries @CharlieDalsass. I would recommend using babel to compile it down to ES5 for production code.
  • adamwdraper
    adamwdraper over 7 years
    Numeral.js is active again.
  • Akshay Vijay Jain
    Akshay Vijay Jain over 7 years
    in order to handle negative number properly prepend following code before returning num=="-" ? acc:<br>i.e. function passed to reduce method will be <br>function(acc, num, i, orig) { return num=="-" ? acc:num + (i && !(i % 3) ? "," : "") + acc; }
  • JensB
    JensB over 7 years
    Because I dont like code I can't read I rewrote it to be more developer friendly here: syntaxwarriors.com/p/18/Format-currency-in-Javascript Pretty much the same thing but readable.
  • flq
    flq over 7 years
    Pretty sure a quite high % of browsers now support this. This should be upvoted much more.
  • Victor Dombrovsky
    Victor Dombrovsky over 7 years
    A non-minified version: josscrowcroft.com/2011/code/… (see "JavaScript Money Format").
  • VisioN
    VisioN over 7 years
    @aross Unfortunately Intl API is still not available in many browsers which are widely used and this solution will make sense when compatibility requirements feature IE9, IE10, Safari 9, etc.
  • VisioN
    VisioN over 7 years
    @aross Often including 2-3 lines of code is faster and easier than embedding 50+Kb library to get the same result. It depends on the thing you are actually doing. I still use this code in my projects when I simply need to format a number in a straightforward format.
  • VisioN
    VisioN over 7 years
    @aross My experience tells the opposite: this code is enough in 90% of all the cases. I don't know what Indial digit grouping is but I'm sure this solution can be easily customised for it. Get me right, I don't say that this answer is the best one nowadays in 2017 but I'm quite confident that developers will still find it useful.
  • Evgeny
    Evgeny about 7 years
    This is fully supported as of 2017 and should be the only correct answer
  • Gerard ONeill
    Gerard ONeill about 7 years
    VisioN, you are correct -- I'm selecting the first of your short solutions -- which, by the way, is a brilliant regex! Thank you for sharing it, I've gained a neuron.
  • Admin
    Admin almost 7 years
    But how to do it as Euro Currency?
  • Admin
    Admin almost 7 years
    But how to do Euro currency? 1.000,00 Euro?
  • synthet1c
    synthet1c almost 7 years
    @YumYumYum I added a full example with more formatting options to allow for more flexibility.
  • Admin
    Admin almost 7 years
    $('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) ); - show 1.000,00 E
  • Mark Carpenter Jr
    Mark Carpenter Jr almost 7 years
    The MDN Documentation for anyone who would like to see the full set of options.
  • Mark Carpenter Jr
    Mark Carpenter Jr almost 7 years
    The toLocaleString() prototype, does the same thing with less code. and is more robust. Answered Here
  • Ethan
    Ethan almost 7 years
    Wow, this is a really great answer. Should be top.
  • Patrick Roberts
    Patrick Roberts almost 7 years
    I personally think this solution is garbage. You don't use sensical variable names, you modify the prototype of a built-in with an enumerable property, and your code doesn't even make sense, even if it does work.
  • Sprose
    Sprose over 6 years
    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!
  • aross
    aross over 6 years
    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.
  • Captain Hypertext
    Captain Hypertext over 6 years
    This answer is somewhat outdated now. See the answer about Intl.numberformat below
  • aron
    aron about 6 years
    simple, but no comma for 1,000
  • Serj Sagan
    Serj Sagan about 6 years
    Horrible use of variable names!
  • Horacio
    Horacio almost 6 years
    If for some reason you don't want cents, you can change decimal precision with: minimumFractionDigits: 0
  • Burak
    Burak almost 6 years
    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.
  • Alexander
    Alexander almost 6 years
    Regarding @Burak comment. I don't think this is the case. For me the code "var currency = "$"+Number(someNumber.toFixed(2)).toLocaleString()" turns var someNumber = 2345667.7899; into $2,345,667.79 which is what I need.
  • flyandi
    flyandi almost 6 years
    Works great in React Native as well!
  • Burak
    Burak almost 6 years
    @Alexander but what if someNumber is "234567" or "234567.8"? Then you have zero or one decimals, instead of two, which isn't what OP wants and generally seems undesired for currency formatting too.
  • Alexander
    Alexander almost 6 years
    Yes, you are correct. The one I now use is the prototype Number.prototype.formatMoney which is identified below.
  • Bacon Brad
    Bacon Brad almost 6 years
    Code on this site should favor readability for people, not web browsers.
  • Kabir Sarin
    Kabir Sarin over 5 years
    It's 2018 and this is basically supported everywhere. This should be the correct answer.
  • Avernikoz
    Avernikoz over 5 years
    My TS version that works for many cases: export const formatNumberToUSFormat = (numberToFormat: number | string) => { const stringNumber = numberToFormat.toString() return stringNumber.match(/\./g) ? stringNumber.replace(/\d(?=(\d{3})+\.)/g, '$&,') : stringNumber.replace(/\d(?=(\d{3})+$)/g, '$&,') }
  • Robin Wilson
    Robin Wilson over 5 years
    If the date could be null then you need to call the function like this: formatMoney(someDate, 2) instead of someDate.formatMoney(2) otherwise you get "Uncaught TypeError: Cannot read property 'value' of null" when it is.
  • Nick Grealy
    Nick Grealy about 5 years
    @Horacio / Nico - See earlier answer: stackoverflow.com/a/18994850/782034
  • Caio Mar
    Caio Mar almost 5 years
    I'm surprised no one mentioned that the line j = (j = i.length) > 3 ? j % 3 : 0; is calling for j before it is defined
  • Jakub Keller
    Jakub Keller almost 5 years
    This code is hard to follow. At least give some names to the parameters.
  • oldboy
    oldboy almost 5 years
    the best answer by far
  • n8jadams
    n8jadams almost 5 years
    I needed something to work in both the browser and in an old version of Node. This worked perfectly. Thanks
  • avenmore
    avenmore over 4 years
    This does not get the commonly used format for en-ZA/ZAR (South Africa) correct, so if you are in a outlying region you may be at the mercy of what an outsider has guessed your format should be.
  • Nick Grealy
    Nick Grealy over 4 years
    @avenmore works for latest versions of Chrome/Firefox/Safari. I hate to ask... but what browser & version are you testing on?
  • avenmore
    avenmore over 4 years
    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.
  • Nick Grealy
    Nick Grealy over 4 years
    @avenmore ... interesting... I did a bit of investigation, and TLDR; comma is the official decimal separator for South Africa. "When South Africa adopted the metric system, it adopted the comma as its decimal separator, although a number of house styles, including some English-language newspapers such as The Sunday Times, continue to use the full stop" - en.wikipedia.org/wiki/Decimal_separator. However, you can switch formats by using (2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2})
  • avenmore
    avenmore over 4 years
    @Nick Grealy Thanks for the investigation, it is the bane of South African software people - having things break from an unexpected comma. I did try the params you suggest but it produced "ZAR 2,500.00", also not acceptable.
  • Simon East
    Simon East over 4 years
    This option doesn't put a comma between the thousands. :-(
  • Tim
    Tim over 4 years
    minimumFractionDigits: 2 just what I was looking for!
  • ryanm
    ryanm over 4 years
    WARNING! The non-ES6 code is not functional as of 10/31/2019, I am surprised it got so many upvotes! Please correct the following simple cases: 100000 (results in 100000.00) and 1000000 (results in 1,000000.00)
  • acido
    acido over 4 years
    The Number() is mandatory if the var is a string or any other type. This helped me a lot! thanks for sharing it.
  • beliha
    beliha over 4 years
    non ES6 code doesn't work, there is somethign wrong with the regExpression used, I haven't brushed up on my reg ex in years so I can't fix it unfortunatley
  • Matt Jensen
    Matt Jensen over 4 years
    Support as far back as Internet Explorer 11 (IE 11), with all major browsers supporting as well.
  • beliha
    beliha about 4 years
    Cleaner non ES6: function formatMoney(amount, decimalCount, decimal, thousands) { decimalCount = Math.abs(decimalCount); decimalCount = isNaN(decimalCount) ? 2 : decimalCount; var negativeSign = amount < 0 ? "-" : ""; var i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString(); var 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) : ""); }
  • Amzad Khan
    Amzad Khan about 4 years
    After decimal you want only two (2) digits for example, suppose your currency format is this 22.2737, at that time you can use following solution for getting result in this format 22.27, function currencyFormat(num){ return parseFloat(num).toFixed(2); } var moneyWithDecimal = currencyFormat(22.2737); alert(moneyWithDecimal );
  • olaoluwa_98
    olaoluwa_98 about 4 years
    This is an awesome solution! but I tried it for a number starting with 0 e.g (012345).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,') It returns "5,349.00" instead of "12,345.00"
  • VisioN
    VisioN about 4 years
    @olaoluwa_98 Numbers that start with zero are considered to be octal literals, so 012345 is 5349 in decimal notation. You are not allowed to use octal literals in strict mode.
  • Cegone
    Cegone almost 4 years
    I agree with @Burak, why this is best answer so far.. anyone tried? it is not giving expected output
  • user1556937
    user1556937 almost 4 years
    is there a way to discredit this answer. its no longer relevant.
  • RkuangDev
    RkuangDev over 3 years
    is there a way to reverse this getting $2,500.00 back to a string like 2500.00
  • aross
    aross over 3 years
    @RkuangDev Sure, but you need to know the decimal separator used. If it's a dot (easiest scenario), this will work: parseFloat('$2,345.67'.replace(/[^0-9.]/g, '')). Beware of floats for currency, of course
  • Paulo Bueno
    Paulo Bueno over 3 years
    My 2 cents: for non-imperial(ists) guys(7642818.78).toFixed(2).replace(".",",").replace(/\d(?=(‌​\d{3})+\,)/g, '$&.')
  • TheGeekZn
    TheGeekZn over 3 years
    Everyone just vote-down this answer so the proper answer can be more visible
  • Olawale Oladiran
    Olawale Oladiran over 3 years
    How come this is not the accepted answer. Works beautifully!
  • Martin Braun
    Martin Braun over 3 years
    I'd like to nominate this answer to be the most upvoted answer that needs to be down voted for heavens sake.
  • guilieen
    guilieen over 3 years
    How to do that with a event in input when typing?
  • wilmol
    wilmol over 3 years
    These inbuilt format functions are inconsistent (require locale data...) so this regex is a lifesaver.
  • Marco Demaio
    Marco Demaio over 3 years
    @AntonPRobul it's not true you can test it with JS FIddle link added in the answer, (2030).toMoney(0, '.', ' '); produces this: "2 030" which is the expected result since you are telling the function to use a single whitespace as thousands separator.
  • Mike Jarema
    Mike Jarema about 3 years
    The "Custom function" code is incorrect. For example when running the code snippet, 1234567.12 is returned as 1,234567.12, it's just plain wrong.
  • Harrison
    Harrison about 3 years
    This is amazing! Should be the best answers,!
  • Aljosha Novakovic
    Aljosha Novakovic about 3 years
    Add maximumFractionDigits: 0 if you want the answer in the form of $2,500. So it would be: return (num).toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
  • aross
    aross about 3 years
    @AljoshaNovakovic Correct, that's already in the answer as well :)
  • Aljosha Novakovic
    Aljosha Novakovic about 3 years
    ahh yeah didn't see in the comments. Good answer!
  • JotaPardo
    JotaPardo about 3 years
    I had to add the line let j = 0; before using j. Issues with the code in some developers browsers... But in other cases still working. Weird.
  • JotaPardo
    JotaPardo about 3 years
    I had to add the line let j = 0; before using j. Issues with the code in some developers browsers... But in other cases still working. Weird.
  • Peter Mortensen
    Peter Mortensen about 3 years
    An explanation would be in order. E.g., what is the idea/gist? How is it different from previous answers?
  • Wayne
    Wayne about 3 years
    The edit to support negative numbers doesn't actually seem to work
  • Peter Mortensen
    Peter Mortensen almost 3 years
    Does it work? 10 years should be enough to have figured it out. Or is it a rhetorical question?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    How can it be the best one if it produces wrong output?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order. At a minimum a statement about what range of numbers it is supposed to work for. You could also include some sample input and output (e.g., you could use some sample inputs from other answers).
  • Peter Mortensen
    Peter Mortensen almost 3 years
    @Bhargav Nanekalva: It is actually in JavaScript.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    The first link is (effectively) broken: "Page not found"
  • Peter Mortensen
    Peter Mortensen almost 3 years
    Re "a lot of bugs in the code": Three places that look suspicious: l=l-v.length (is in a Boolean context/comparison), return "\"+"+f+"+\""; (missing escapes?), and return new Function("_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex); (is that valid syntax? - not a rhetorical question).
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order. E.g., what is the purpose of ar[0] | 0?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    Is <script language=="Javascript"> valid syntax (not a rhetorical question)?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    What is the difference between theEvent.preventDefault and theEvent.preventDefault()? (Used in the same construct)
  • Peter Mortensen
    Peter Mortensen almost 3 years
    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)?
  • aross
    aross almost 3 years
    Do you have anything different from this answer? stackoverflow.com/a/16233919/1000608
  • aross
    aross over 2 years
    By choosing the regex answer while your requirements were more complicated you put yourself in a tough spot. You could just have used maximumFractionDigits, as described here.
  • Md. Rejaul Karim
    Md. Rejaul Karim over 2 years
    Not work with negative number
  • Wayne
    Wayne over 2 years
    @Md.RejaulKarim Yeah, that was a bad edit. I've fixed it with a much more elegant solution. (You always want to output the value of num prepended to acc; the only question is whether to include a comma between the two. That's the check that should have been updated.)
  • Diego Leonvendagar
    Diego Leonvendagar over 2 years
    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?
  • Qiqo
    Qiqo about 2 years
    upvoting this in 2022. This should be the accepted answer for wide compatibility and simplicity (as it should be)
  • Josh Bonnick
    Josh Bonnick about 2 years
    I had an issue with Chrome version 87 and below using maximumFractionDigits: 0 - refuses to use 0 as it's value.
  • aross
    aross about 2 years
    @JoshBonnick That probably happened due to incomplete/outdated libICU used. Possibly platform related, if Chrome tries to use (or tried to) the system ICU rather than a shipped one.
  • Josh Bonnick
    Josh Bonnick about 2 years
    @aross It ended up being because the default value for minimumFractionDigits was 2 - so min 2 and max 0 caused a Invalid range error - took me a while to figure this out, v88+ just accepted a max of 0
  • aross
    aross about 2 years
    @JoshBonnick Funny, Firefox never had this issue so sounds like a Chrome bug then.