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?
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?
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.
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 */
en-US
out of the box. One solution is to install full-icu, see here for more informationThis 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.
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,
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>
(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/
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/
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/
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});
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.
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:
moved a bit the Math.abs(decimals)
to be done only when is not NaN
.
decimal_sep
can not be empty string any more (a some sort of decimal separator is a must)
we use typeof thousands_sep === 'undefined'
as suggested in How best to determine if an argument is not sent to the JavaScript function
(+n || 0)
is not needed because this
is a Number
object
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.
accounting.js is a tiny JavaScript library for number, money and currency formatting.
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"
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"
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
I think you want:
f.nettotal.value = "$" + showValue.toFixed(2);
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...
Numeral.js - a JavaScript library for easy number formatting by @adamwdraper
numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
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! :)
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)
)
javascript-number-formatter (formerly at Google Code)
#,##0.00
or with negation -000.####
.# ##0,00
, #,###.##
, #'###.##
or any type of non-numbering symbol.#,##,#0.000
or #,###0.##
are all valid.##,###,##.#
or 0#,#00#.###0#
are all OK.format( "0.0000", 3.141592)
.(excerpt from its README)
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());
+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) : "");
};
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)));">
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'
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];
}
There is a built-in function, toFixed, in JavaScript:
var num = new Number(349);
document.write("$" + num.toFixed(2));
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.
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
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));
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);
}
}
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"
Number(value)
.toFixed(2)
.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
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.
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('.');
}
}
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('.');
};
}
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('.');
};
}
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('');
};
}
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));
}
If we want custom a thousands separator or decimal separator, use replace()
:
123456.78.format(2).replace(',', ' ').replace('.', ' ');
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);
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();
I found this from: accounting.js. It's very easy and perfectly fits my need.
// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00
// European formatting (custom symbol and separators), can also use options object as second parameter:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99
// Negative values can be formatted nicely:
accounting.formatMoney(-500000, "£ ", 0); // £ -500,000
// Simple `format` string allows control of symbol position (%v = value, %s = symbol):
accounting.formatMoney(5318008, { symbol: "GBP", format: "%v %s" }); // 5,318,008.00 GBP
// Euro currency symbol to the right
accounting.formatMoney(5318008, {symbol: "€", precision: 2, thousand: ".", decimal : ",", format: "%v%s"}); // 1.008,00€
A simple option for proper comma placement by reversing the string first and basic regexp.
String.prototype.reverse = function() {
return this.split('').reverse().join('');
};
Number.prototype.toCurrency = function( round_decimal /*boolean*/ ) {
// format decimal or round to nearest integer
var n = this.toFixed( round_decimal ? 0 : 2 );
// convert to a string, add commas every 3 digits from left to right
// by reversing string
return (n + '').reverse().replace( /(\d{3})(?=\d)/g, '$1,' ).reverse();
};
The YUI codebase uses the following formatting:
format: function(nData, oConfig) {
oConfig = oConfig || {};
if(!YAHOO.lang.isNumber(nData)) {
nData *= 1;
}
if(YAHOO.lang.isNumber(nData)) {
var sOutput = nData + "";
var sDecimalSeparator = (oConfig.decimalSeparator) ? oConfig.decimalSeparator : ".";
var nDotIndex;
// Manage decimals
if(YAHOO.lang.isNumber(oConfig.decimalPlaces)) {
// Round to the correct decimal place
var nDecimalPlaces = oConfig.decimalPlaces;
var nDecimal = Math.pow(10, nDecimalPlaces);
sOutput = Math.round(nData*nDecimal)/nDecimal + "";
nDotIndex = sOutput.lastIndexOf(".");
if(nDecimalPlaces > 0) {
// Add the decimal separator
if(nDotIndex < 0) {
sOutput += sDecimalSeparator;
nDotIndex = sOutput.length-1;
}
// Replace the "."
else if(sDecimalSeparator !== "."){
sOutput = sOutput.replace(".",sDecimalSeparator);
}
// Add missing zeros
while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
sOutput += "0";
}
}
}
// Add the thousands separator
if(oConfig.thousandsSeparator) {
var sThousandsSeparator = oConfig.thousandsSeparator;
nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
var sNewOutput = sOutput.substring(nDotIndex);
var nCount = -1;
for (var i=nDotIndex; i>0; i--) {
nCount++;
if ((nCount%3 === 0) && (i !== nDotIndex)) {
sNewOutput = sThousandsSeparator + sNewOutput;
}
sNewOutput = sOutput.charAt(i-1) + sNewOutput;
}
sOutput = sNewOutput;
}
// Prepend prefix
sOutput = (oConfig.prefix) ? oConfig.prefix + sOutput : sOutput;
// Append suffix
sOutput = (oConfig.suffix) ? sOutput + oConfig.suffix : sOutput;
return sOutput;
}
// Still not a number. Just return it unaltered
else {
return nData;
}
}
It would need editing as the YUI library is configurable, like replacing oConfig.decimalSeparator with ".".
Patrick Desjardins (ex Daok)'s example worked well for me. I ported it over to CoffeeScript if anyone is interested.
Number.prototype.toMoney = (decimals = 2, decimal_separator = ".", thousands_separator = ",") ->
n = this
c = if isNaN(decimals) then 2 else Math.abs decimals
sign = if n < 0 then "-" else ""
i = parseInt(n = Math.abs(n).toFixed(c)) + ''
j = if (j = i.length) > 3 then j % 3 else 0
x = if j then i.substr(0, j) + thousands_separator else ''
y = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_separator)
z = if c then decimal_separator + Math.abs(n - i).toFixed(c).slice(2) else ''
sign + x + y + z
A minimalistic approach that just meets the original requirements:
function formatMoney(n) {
return "$ " + (Math.round(n * 100) / 100).toLocaleString();
}
@Daniel Magliola: You're right. The above was a hasty, incomplete implementation. Here's the corrected implementation:
function formatMoney(n) {
return "$ " + n.toLocaleString().split(".")[0] + "."
+ n.toFixed(2).split(".")[1];
}
tggagne is correct. My solution below is not good due to float rounding. And the toLocaleString function lacks some browser support. I'll leave the below comments for archival purposes of what not to do. :)
Date.prototype.toLocaleString()
(Old Solution) Use Patrick Desjardins' solution instead.
This is a terse solution that uses toLocaleString(), which has been supported since JavaScript version 1.0. This example designates the currency to U.S. Dollars, but could be switched to pounds by using 'GBP' instead of 'USD'.
var formatMoney = function (value) {
// Convert the value to a floating point number in case it arrives as a string.
var numeric = parseFloat(value);
// Specify the local currency.
return numeric.toLocaleString('USD', { style: 'currency', currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
See Internationalization and localization, Currencies for additional details.
A function to handle currency output, including negatives.
Sample Output:
$5.23
-$5.23
function formatCurrency(total) {
var neg = false;
if(total < 0) {
neg = true;
total = Math.abs(total);
}
return (neg ? "-$" : '$') + parseFloat(total, 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString();
}
Another way:
function centsToDollaString(x){
var cents = x + ""
while(cents.length < 4){
cents = "0" + cents;
}
var dollars = cents.substr(0,cents.length - 2)
var decimal = cents.substr(cents.length - 2, 2)
while(dollars.length % 3 != 0){
dollars = "0" + dollars;
}
str = dollars.replace(/(\d{3})(?=\d)/g, "$1" + ",").replace(/^0*(?=.)/, "");
return "$" + str + "." + decimal;
}
http://code.google.com/p/javascript-number-formatter/:
UPDATE This is my home-grown pp
utilities for most common tasks:
var NumUtil = {};
/**
Petty print 'num' wth exactly 'signif' digits.
pp(123.45, 2) == "120"
pp(0.012343, 3) == "0.0123"
pp(1.2, 3) == "1.20"
*/
NumUtil.pp = function(num, signif) {
if (typeof(num) !== "number")
throw 'NumUtil.pp: num is not a number!';
if (isNaN(num))
throw 'NumUtil.pp: num is NaN!';
if (num < 1e-15 || num > 1e15)
return num;
var r = Math.log(num)/Math.LN10;
var dot = Math.floor(r) - (signif-1);
r = r - Math.floor(r) + (signif-1);
r = Math.round(Math.exp(r * Math.LN10)).toString();
if (dot >= 0) {
for (; dot > 0; dot -= 1)
r += "0";
return r;
} else if (-dot >= r.length) {
var p = "0.";
for (; -dot > r.length; dot += 1) {
p += "0";
}
return p+r;
} else {
return r.substring(0, r.length + dot) + "." + r.substring(r.length + dot);
}
}
/** Append leading zeros up to 2 digits. */
NumUtil.align2 = function(v) {
if (v < 10)
return "0"+v;
return ""+v;
}
/** Append leading zeros up to 3 digits. */
NumUtil.align3 = function(v) {
if (v < 10)
return "00"+v;
else if (v < 100)
return "0"+v;
return ""+v;
}
NumUtil.integer = {};
/** Round to integer and group by 3 digits. */
NumUtil.integer.pp = function(num) {
if (typeof(num) !== "number") {
console.log("%s", new Error().stack);
throw 'NumUtil.integer.pp: num is not a number!';
}
if (isNaN(num))
throw 'NumUtil.integer.pp: num is NaN!';
if (num > 1e15)
return num;
if (num < 0)
throw 'Negative num!';
num = Math.round(num);
var group = num % 1000;
var integ = Math.floor(num / 1000);
if (integ === 0) {
return group;
}
num = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + num;
num = NumUtil.align3(group) + " " + num;
}
return num;
}
NumUtil.currency = {};
/** Round to coins and group by 3 digits. */
NumUtil.currency.pp = function(amount) {
if (typeof(amount) !== "number")
throw 'NumUtil.currency.pp: amount is not a number!';
if (isNaN(amount))
throw 'NumUtil.currency.pp: amount is NaN!';
if (amount > 1e15)
return amount;
if (amount < 0)
throw 'Negative amount!';
if (amount < 1e-2)
return 0;
var v = Math.round(amount*100);
var integ = Math.floor(v / 100);
var frac = NumUtil.align2(v % 100);
var group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0) {
return group + "." + frac;
}
amount = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + amount + "." + frac;
amount = NumUtil.align3(group) + " " + amount;
}
return amount;
}
var number = 3500;
alert(new Intl.NumberFormat().format(number));
// → "3,500" if in US English locale
We can also use numeraljs
Numbers can be formatted to look like currency, percentages, times, or even plain old numbers with decimal places, thousands, and abbreviations. And you can always create a custom format.
var string = numeral(1000).format('0,0');
// '1,000'
This answer meets the following criteria:
This code is built on concepts from other answers. Its execution speed should be among the better posted here if that's a concern.
var decimalCharacter = Number("1.1").toLocaleString().substr(1,1);
var defaultCurrencyMarker = "$";
function formatCurrency(number, currencyMarker) {
if (typeof number != "number")
number = parseFloat(number, 10);
// if NaN is passed in or comes from the parseFloat, set it to 0.
if (isNaN(number))
number = 0;
var sign = number < 0 ? "-" : "";
number = Math.abs(number); // so our signage goes before the $ symbol.
var integral = Math.floor(number);
var formattedIntegral = integral.toLocaleString();
// IE returns "##.00" while others return "##"
formattedIntegral = formattedIntegral.split(decimalCharacter)[0];
var decimal = Math.round((number - integral) * 100);
return sign + (currencyMarker || defaultCurrencyMarker) +
formattedIntegral +
decimalCharacter +
decimal.toString() + (decimal < 10 ? "0" : "");
}
These tests only work on a US locale machine. This decision was made for simplicity and because this could cause of crappy input (bad auto-localization) allowing for crappy output issues.
var tests = [
// [ input, expected result ]
[123123, "$123,123.00"], // no decimal
[123123.123, "$123,123.12"], // decimal rounded down
[123123.126, "$123,123.13"], // decimal rounded up
[123123.4, "$123,123.40"], // single decimal
["123123", "$123,123.00"], // repeat subset of the above using string input.
["123123.123", "$123,123.12"],
["123123.126", "$123,123.13"],
[-123, "-$123.00"] // negatives
];
for (var testIndex=0; testIndex < tests.length; testIndex++) {
var test = tests[testIndex];
var formatted = formatCurrency(test[0]);
if (formatted == test[1]) {
console.log("Test passed, \"" + test[0] + "\" resulted in \"" + formatted + "\"");
} else {
console.error("Test failed. Expected \"" + test[1] + "\", got \"" + formatted + "\"");
}
}
Here is the short and best one to convert numbers into a currency format:
function toCurrency(amount){
return amount.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
// usage: toCurrency(3939920.3030);
The code from Jonathan M looked too complicated for me, so I rewrote it and got about 30% on Firefox v30 and 60% on Chrome v35 speed boost (http://jsperf.com/number-formating2):
Number.prototype.formatNumber = function(decPlaces, thouSeparator, decSeparator) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator == undefined ? "." : decSeparator;
thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
var n = this.toFixed(decPlaces);
if (decPlaces) {
var i = n.substr(0, n.length - (decPlaces + 1));
var j = decSeparator + n.substr(-decPlaces);
} else {
i = n;
j = '';
}
function reverse(str) {
var sr = '';
for (var l = str.length - 1; l >= 0; l--) {
sr += str.charAt(l);
}
return sr;
}
if (parseInt(i)) {
i = reverse(reverse(i).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator));
}
return i + j;
};
Usage:
var sum = 123456789.5698;
var formatted = '$' + sum.formatNumber(2, ',', '.'); // "$123,456,789.57"
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat Example: Using locales
This example shows some of the variations in localized number formats. In order to get the format of the language used in the user interface of your application, make sure to specify that language (and possibly some fallback languages) using the locales argument:
var number = 123456.789;
// German uses comma as decimal separator and period for thousands console.log(new Intl.NumberFormat('de-DE').format(number)); // → 123.456,789
// Arabic in most Arabic speaking countries uses real Arabic digits console.log(new Intl.NumberFormat('ar-EG').format(number)); // → ١٢٣٤٥٦٫٧٨٩
// India uses thousands/lakh/crore separators console.log(new Intl.NumberFormat('en-IN').format(number));
This might work:
function format_currency(v, number_of_decimals, decimal_separator, currency_sign){
return (isNaN(v)? v : currency_sign + parseInt(v||0).toLocaleString() + decimal_separator + (v*1).toFixed(number_of_decimals).slice(-number_of_decimals));
}
No loops, no regexes, no arrays, no exotic conditionals.
A quicker way with regexp:
Number.prototype.toMonetaryString = function() {
var n = this.toFixed(2), m;
//var = this.toFixed(2).replace(/\./, ','); For comma separator
// with a space for thousands separator
while ((m = n.replace(/(\d)(\d\d\d)\b/g, '$1 $2')) != n)
n = m;
return m;
}
String.prototype.fromMonetaryToNumber = function(s) {
return this.replace(/[^\d-]+/g, '')/100;
}
There is no equivalent of "formatNumber" in JavaScript. You can write it yourself or find a library that already does this.
Here is a mootools 1.2 implementation from the code provided by XMLilley...
Number.implement('format', function(decPlaces, thouSeparator, decSeparator){
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator === undefined ? '.' : decSeparator;
thouSeparator = thouSeparator === undefined ? ',' : thouSeparator;
var num = this,
sign = num < 0 ? '-' : '',
i = parseInt(num = Math.abs(+num || 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(num - i).toFixed(decPlaces).slice(2) : '');
});
I based this heavily on the answer from VisioN:
function format (val) {
val = (+val).toLocaleString();
val = (+val).toFixed(2);
val += "";
return val.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1" + format.thousands);
}
(function (isUS) {
format.decimal = isUS ? "." : ",";
format.thousands = isUS ? "," : ".";
}(("" + (+(0.00).toLocaleString()).toFixed(2)).indexOf(".") > 0));
I tested with inputs:
[ ""
, "1"
, "12"
, "123"
, "1234"
, "12345"
, "123456"
, "1234567"
, "12345678"
, "123456789"
, "1234567890"
, ".12"
, "1.12"
, "12.12"
, "123.12"
, "1234.12"
, "12345.12"
, "123456.12"
, "1234567.12"
, "12345678.12"
, "123456789.12"
, "1234567890.12"
, "1234567890.123"
, "1234567890.125"
].forEach(function (item) {
console.log(format(item));
});
And got these results:
0.00
1.00
12.00
123.00
1,234.00
12,345.00
123,456.00
1,234,567.00
12,345,678.00
123,456,789.00
1,234,567,890.00
0.12
1.12
12.12
123.12
1,234.12
12,345.12
123,456.12
1,234,567.12
12,345,678.12
123,456,789.12
1,234,567,890.12
1,234,567,890.12
1,234,567,890.13
Just for fun.
I like the shortest answer by VisionN except when I need to modify it for a number without a decimal point ($123 instead of $123.00). It does not work, so instead of quick copy/paste I need to decipher the arcane syntax of the JavaScript regular expression.
Here is the original solution
n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
I'll make it a bit longer:
var re = /\d(?=(\d{3})+\.)/g;
var subst = '$&,';
n.toFixed(2).replace(re, subst);
The re
part here (search part in string replace) means
\d
)?=
...) (lookahead)(
...)+
\d{3}
)\.
)g
)The subst
part here means:
$&
), followed by a comma.As we use string.replace
, all other text in the string remains the same and only found digits (those that are followed by 3, 6, 9, etc. other digits) get an additional comma.
So in a number, 1234567.89, digits 1 and 4 meet the condition (1234567.89) and are replaced with "1," and "4," resulting in 1,234,567.89.
If we don't need the decimal point in dollar amount at all (i.e., $123 instead of $123.00), we may change the regular expression like this:
var re2 = /\d(?=(\d{3})+$)/g;
It relies on the end of line ($
) instead of a dot (\.
) and the final expression will be (notice also toFixed(0)
):
n.toFixed(0).replace(/\d(?=(\d{3})+$)/g, '$&,');
This expression will give
1234567.89 -> 1,234,567
Also instead of end of line ($
) in the regular expression above, you may opt for a word boundary as well (\b
).
My apology in advance if I misinterpreted any part of the regular expression handling.
Many of the answers had helpful ideas, but none of them could fit my needs. So I used all the ideas and build this example:
function Format_Numb(fmt){
var decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
if(typeof decSgn === "undefined") decSgn = ".";
if(typeof kommaSgn === "undefined") kommaSgn= ",";
var s3digits = /(\d{1,3}(?=(\d{3})+(?=[.]|$))|(?:[.]\d*))/g;
var dflt_nk = "00000000".substring(0, decimals);
//--------------------------------
// handler for pattern: "%m"
var _f_money = function(v_in){
var v = v_in.toFixed(decimals);
var add_nk = ",00";
var arr = v.split(".");
return arr[0].toString().replace(s3digits, function ($0) {
return ($0.charAt(0) == ".")
? ((add_nk = ""), (kommaSgn + $0.substring(1)))
: ($0 + decSgn);
})
+ ((decimals > 0)
? (kommaSgn
+ (
(arr.length > 1)
? arr[1]
: dflt_nk
)
)
: ""
);
}
// handler for pattern: "%<len>[.<prec>]f"
var _f_flt = function(v_in, l, prec){
var v = (typeof prec !== "undefined") ? v_in.toFixed(prec) : v_in;
return ((typeof l !== "undefined") && ((l=l-v.length) > 0))
? (Array(l+1).join(" ") + v)
: v;
}
// handler for pattern: "%<len>x"
var _f_hex = function(v_in, l, flUpper){
var v = Math.round(v_in).toString(16);
if(flUpper) v = v.toUpperCase();
return ((typeof l !== "undefined") && ((l=l-v.length) > 0))
? (Array(l+1).join("0") + v)
: v;
}
//...can be extended..., just add the function, for example: var _f_octal = function( v_in,...){
//--------------------------------
if(typeof(fmt) !== "undefined"){
//...can be extended..., just add the char, for example "O": MFX -> MFXO
var rpatt = /(?:%([^%"MFX]*)([MFX]))|(?:"([^"]*)")|("|%%)/gi;
var _qu = "\"";
var _mask_qu = "\\\"";
var str = fmt.toString().replace(rpatt, function($0, $1, $2, $3, $4){
var f;
if(typeof $1 !== "undefined"){
switch($2.toUpperCase()){
case "M": f = "_f_money(v)"; break;
case "F": var n_dig0, n_dig1;
var re_flt =/^(?:(\d))*(?:[.](\d))*$/;
$1.replace(re_flt, function($0, $1, $2){
n_dig0 = $1;
n_dig1 = $2;
});
f = "_f_flt(v, " + n_dig0 + "," + n_dig1 + ")"; break;
case "X": var n_dig = "undefined";
var re_flt = /^(\d*)$/;
$1.replace(re_flt, function($0){
if($0 != "") n_dig = $0;
});
f = "_f_hex(v, " + n_dig + "," + ($2=="X") + ")"; break;
//...can be extended..., for example: case "O":
}
return "\"+"+f+"+\"";
} else if(typeof $3 !== "undefined"){
return _mask_qu + $3 + _mask_qu;
} else {
return ($4 == _qu) ? _mask_qu : $4.charAt(0);
}
});
var cmd = "return function(v){"
+ "if(typeof v === \"undefined\")return \"\";" // null returned as empty string
+ "if(!v.toFixed) return v.toString();" // not numb returned as string
+ "return \"" + str + "\";"
+ "}";
//...can be extended..., just add the function name in the 2 places:
return new Function("_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex);
}
}
First, I needed a C-style format-string-definition that should be flexible, but very easy to use and I defined it in following way; patterns:
%[<len>][.<prec>]f float, example "%f", "%8.2d", "%.3f"
%m money
%[<len>]x hexadecimal lower case, example "%x", "%8x"
%[<len>]X hexadecimal upper case, example "%X", "%8X"
Because there isn't any need to format others than to euro for me, I implemented only "%m".
But it's easy to extend this... Like in C, the format string is a string containing the patterns. For example, for euro: "%m €" (returns strings like "8.129,33 €")
Besides the flexibility, I needed a very fast solution for processing tables. That means that, when processing thousands of cells, the processing of format string must not be done more than once. A call like "format( value, fmt)" is not acceptable for me, but this must be split into two steps:
// var formatter = Format_Numb( "%m €");
// simple example for Euro...
// but we use a complex example:
var formatter = Format_Numb("a%%%3mxx \"zz\"%8.2f°\" >0x%8X<");
// formatter is now a function, which can be used more than once (this is an example, that can be tested:)
var v1 = formatter(1897654.8198344);
var v2 = formatter(4.2);
... (and thousands of rows)
Also for performance, _f_money encloses the regular expression;
Third, a call like "format( value, fmt)" is not acceptable because:
Although it should be possible to format different collections of objects (for example, cells of a column) with different masks, I don't want to have something to handle format strings at the point of processing. At this point I only want to use formatting, like in
for( var cell in cells){ do_something( cell.col.formatter( cell.value)); }
What format - maybe it's defined in an .ini file, in an XML for each column or somewhere else ..., but analyzing and setting formats or dealing with internationalizaton is processed in totally another place, and there I want to assign the formatter to the collection without thinking about performance issues:
col.formatter = Format_Numb( _getFormatForColumn(...) );
Fourth, I wanted an "tolerant" solution, so passing, for example, a string instead of a number should return simply the string, but "null" should return en empty string.
(Also formatting "%4.2f" must not cut something if the value is too big.)
And last, but not least - it should be readable and easy extendable, without having any effects in performance... For example, if somebody needs "octal values", please refer to lines with "...can be extended..." - I think that should be a very easy task.
My overall focus lay on performance. Each "processing routine" (for example, _f_money
) can be encapsulated optimized or exchanged with other ideas in this or other threads without change of the "prepare routines" (analyze format strings and creation of the functions), which must only be processed once and in that sense are not so performance critical like the conversion calls of thousands of numbers.
For all, who prefer methods of numbers:
Number.prototype.format_euro = (function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%m €"));
var v_euro = (8192.3282).format_euro(); // results: 8.192,33 €
Number.prototype.format_hex = (function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%4x"));
var v_hex = (4.3282).format_hex();
Although I tested some, there may be a lot of bugs in the code. So it's not a ready module, but just an idea and a starting point for non-JavaScript experts like me.
The code contains many and little modified ideas from a lot of Stack Overflow posts; sorry I can't reference all of them, but thanks to all the experts.
I had a hard time finding a simple library to work with date and currency, so I created my own: https://github.com/dericeira/slimFormatter.js
Simple as that:
var number = slimFormatter.currency(2000.54);
Because every problem deserves a one-line solution:
Number.prototype.formatCurrency = function() { return this.toFixed(2).toString().split(/[-.]/).reverse().reduceRight(function (t, c, i) { return (i == 2) ? '-' + t : (i == 1) ? t + c.replace(/(\d)(?=(\d{3})+$)/g, '$1,') : t + '.' + c; }, '$'); }
This is easy enough to change for different locales. Just change the '$1,' to '$1.' and '.' to ',' to swap ,
and .
in numbers. The currency symbol can be changed by changing the '$' at the end.
Or, if you have ES6, you can just declare the function with default values:
Number.prototype.formatCurrency = function(thou = ',', dec = '.', sym = '$') { return this.toFixed(2).toString().split(/[-.]/).reverse().reduceRight(function (t, c, i) { return (i == 2) ? '-' + t : (i == 1) ? t + c.replace(/(\d)(?=(\d{3})+$)/g, '$1' + thou) : t + dec + c; }, sym); }
console.log((4215.57).formatCurrency())
$4,215.57
console.log((4216635.57).formatCurrency('.', ','))
$4.216.635,57
console.log((4216635.57).formatCurrency('.', ',', "\u20AC"))
€4.216.635,57
Oh and it works for negative numbers too:
console.log((-6635.574).formatCurrency('.', ',', "\u20AC"))
-€6.635,57
console.log((-1066.507).formatCurrency())
-$1,066.51
And of course you don't have to have a currency symbol:
console.log((1234.586).formatCurrency(',','.',''))
1,234.59
console.log((-7890123.456).formatCurrency(',','.',''))
-7,890,123.46
console.log((1237890.456).formatCurrency('.',',',''))
1.237.890,46
function getMoney(A){
var a = new Number(A);
var b = a.toFixed(2); // Get 12345678.90
a = parseInt(a); // Get 12345678
b = (b-a).toPrecision(2); // Get 0.90
b = parseFloat(b).toFixed(2); // In case we get 0.0, we pad it out to 0.00
a = a.toLocaleString(); // Put in commas - Internet Explorer also puts in .00, so we'll get 12,345,678.00
// If Internet Explorer (our number ends in .00)
if(a < 1 && a.lastIndexOf('.00') == (a.length - 3))
{
a = a.substr(0, a.length-3); // Delete the .00
}
return a + b.substr(1); // Remove the 0 from b, then return a + b = 12,345,678.90
}
alert(getMoney(12345678.9));
This works in Firefox and Internet Explorer.
String.prototype.toPrice = function () {
var v;
if (/^\d+(,\d+)$/.test(this))
v = this.replace(/,/, '.');
else if (/^\d+((,\d{3})*(\.\d+)?)?$/.test(this))
v = this.replace(/,/g, "");
else if (/^\d+((.\d{3})*(,\d+)?)?$/.test(this))
v = this.replace(/\./g, "").replace(/,/, ".");
var x = parseFloat(v).toFixed(2).toString().split("."),
x1 = x[0],
x2 = ((x.length == 2) ? "." + x[1] : ".00"),
exp = /^([0-9]+)(\d{3})/;
while (exp.test(x1))
x1 = x1.replace(exp, "$1" + "," + "$2");
return x1 + x2;
}
alert("123123".toPrice()); //123,123.00
alert("123123,316".toPrice()); //123,123.32
alert("12,312,313.33213".toPrice()); //12,312,313.33
alert("123.312.321,32132".toPrice()); //123,312,321.32
CoffeeScript for Patrick's popular answer:
Number::formatMoney = (decimalPlaces, decimalChar, thousandsChar) ->
n = this
c = decimalPlaces
d = decimalChar
t = thousandsChar
c = (if isNaN(c = Math.abs(c)) then 2 else c)
d = (if d is undefined then "." else d)
t = (if t is undefined then "," else t)
s = (if n < 0 then "-" else "")
i = parseInt(n = Math.abs(+n or 0).toFixed(c)) + ""
j = (if (j = i.length) > 3 then j % 3 else 0)
s + (if j then i.substr(0, j) + t else "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (if c then d + Math.abs(n - i).toFixed(c).slice(2) else "")
There are already good answers. Here's a simple attempt for fun:
function currencyFormat(no) {
var ar = (+no).toFixed(2).split('.');
return [
numberFormat(ar[0] | 0),
'.',
ar[1]
].join('');
}
function numberFormat(no) {
var str = no + '';
var ar = [];
var i = str.length -1;
while(i >= 0) {
ar.push((str[i-2] || '') + (str[i-1] || '') + (str[i] || ''));
i = i-3;
}
return ar.reverse().join(',');
}
Then run some examples:
console.log(
currencyFormat(1),
currencyFormat(1200),
currencyFormat(123),
currencyFormat(9870000),
currencyFormat(12345),
currencyFormat(123456.232)
)
I want to contribute with this:
function toMoney(amount) {
neg = amount.charAt(0);
amount = amount.replace(/\D/g, '');
amount = amount.replace(/\./g, '');
amount = amount.replace(/\-/g, '');
var numAmount = new Number(amount);
amount = numAmount.toFixed(0).replace(/./g, function(c, i, a) {
return i > 0 && c !== "," && (a.length - i) % 3 === 0 ? "." + c : c;
});
if(neg == '-')
return neg + amount;
else
return amount;
}
This allows you to convert numbers in a text box where you are only supposed to put numbers (consider this scenario).
This is going to clean a textbox where there are only supposed to be numbers, even if you paste a string with numbers and letters or any character
<html>
<head>
<script language=="Javascript">
function isNumber(evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
if (key.length == 0)
return;
var regex = /^[0-9\-\b]+$/;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault)
theEvent.preventDefault();
}
}
function toMoney(amount) {
neg = amount.charAt(0);
amount = amount.replace(/\D/g, '');
amount = amount.replace(/\./g, '');
amount = amount.replace(/\-/g, '');
var numAmount = new Number(amount);
amount = numAmount.toFixed(0).replace(/./g, function(c, i, a) {
return i > 0 && c !== "," && (a.length - i) % 3 === 0 ? "." + c : c;
});
if(neg == '-')
return neg + amount;
else
return amount;
}
function clearText(inTxt, newTxt, outTxt) {
inTxt = inTxt.trim();
newTxt = newTxt.trim();
if(inTxt == '' || inTxt == newTxt)
return outTxt;
return inTxt;
}
function fillText(inTxt, outTxt) {
inTxt = inTxt.trim();
if(inTxt != '')
outTxt = inTxt;
return outTxt;
}
</script>
</head>
<body>
$ <input name=reca2 id=reca2 type=text value="0" onFocus="this.value = clearText(this.value, '0', '');" onblur="this.value = fillText(this.value, '0'); this.value = toMoney(this.value);" onKeyPress="isNumber(event);" style="width:80px;" />
</body>
</html>
Here's a straightforward formatter in vanilla JavaScript:
function numberFormatter (num) {
console.log(num)
var wholeAndDecimal = String(num.toFixed(2)).split(".");
console.log(wholeAndDecimal)
var reversedWholeNumber = Array.from(wholeAndDecimal[0]).reverse();
var formattedOutput = [];
reversedWholeNumber.forEach( (digit, index) => {
formattedOutput.push(digit);
if ((index + 1) % 3 === 0 && index < reversedWholeNumber.length - 1) {
formattedOutput.push(",");
}
})
formattedOutput = formattedOutput.reverse().join('') + "." + wholeAndDecimal[1];
return formattedOutput;
}
I wanted a vanilla JavaScript solution that automatically returned the decimal portion.
function formatDollar(amount) {
var dollar = Number(amount).toLocaleString("us", "currency");
// Decimals
var arrAmount = dollar.split(".");
if (arrAmount.length==2) {
var decimal = arrAmount[1];
if (decimal.length==1) {
arrAmount[1] += "0";
}
}
if (arrAmount.length==1) {
arrAmount.push("00");
}
return "$" + arrAmount.join(".");
}
console.log(formatDollar("1812.2");
Here's mine...
function thousandCommas(num) {
num = num.toString().split('.');
var ints = num[0].split('').reverse();
for (var out=[],len=ints.length,i=0; i < len; i++) {
if (i > 0 && (i % 3) === 0) out.push(',');
out.push(ints[i]);
}
out = out.reverse() && out.join('');
if (num.length === 2) out += '.' + num[1];
return out;
}
I like it simple:
function formatPriceUSD(price) {
var strPrice = price.toFixed(2).toString();
var a = strPrice.split('');
if (price > 1000000000)
a.splice(a.length - 12, 0, ',');
if (price > 1000000)
a.splice(a.length - 9, 0, ',');
if (price > 1000)
a.splice(a.length - 6, 0, ',');
return '$' + a.join("");
}
Taking a few of the best rated answers, I combined and made an ECMAScript 2015 (ES6) function that passes ESLint.
export const formatMoney = (
amount,
decimalCount = 2,
decimal = '.',
thousands = ',',
currencySymbol = '$',
) => {
if (typeof Intl === 'object') {
return new Intl.NumberFormat('en-AU', {
style: 'currency',
currency: 'AUD',
}).format(amount);
}
// Fallback if Intl is not present.
try {
const negativeSign = amount < 0 ? '-' : '';
const amountNumber = Math.abs(Number(amount) || 0).toFixed(decimalCount);
const i = parseInt(amountNumber, 10).toString();
const j = i.length > 3 ? i.length % 3 : 0;
return (
currencySymbol +
negativeSign +
(j ? i.substr(0, j) + thousands : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, `$1${thousands}`) +
(decimalCount
? decimal +
Math.abs(amountNumber - i)
.toFixed(decimalCount)
.slice(2)
: '')
);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
return amount;
};
Zero dependency tiny JavaScript library (1kB bytes) by CurrencyRate.today, providing simple way and advanced number, money and currency formatting and removes all formatting/cruft and returns the raw float value.
https://github.com/dejurin/format-money-js
npm install format-money-js
Features:
from: money and currency formatting;
un: removes all formatting/cruft and returns the raw float value.
Examples 1
const { FormatMoney } = require('format-money-js');
const fm = new FormatMoney({
decimals: 2
});
console.log(fm.from(12345.67, { symbol: '$' })); // return string: $12,345.67
console.log(fm.un('€12,345;67')); // return number: 12345.67
Example 2
const { FormatMoney } = require('format-money-js');
const fm = new FormatMoney({
decimals: 2
});
console.log(fm.from(
12345.67,
{ symbol: '$' },
true // Parse, return object
)
);
/* return object:
{
source: 12345.67,
negative: false,
fullAmount: '12,345.67',
amount: '12,345',
decimals: '.67',
symbol: '$'
}*/
you can simply use NumberToCurrency.js which you will covert number or string to currency string with one command
Here is a quick way by using regexp and replace.
function formatCurrency(number, dp, ts) {
var num = parseFloat(number); // Convert to float
var pw; // For Internet Explorer
dp = parseInt(dp, 10); // Decimal point
dp = isNaN(dp) ? 2 : dp; // Default 2 decimal point
ts = ts || ','; // Thousands separator
return num != number ?
false : // Return false for NaN
((0.9).toFixed(0) == '1' ? // For cater Internet Explorer toFixed bug
num.toFixed(dp) : // Format to fix n decimal point with round up
(Math.round(num * (pw = Math.pow(10, dp) || 1)) / pw).toFixed(dp) // For fixing Internet Explorer toFixed bug on round up value like 0.9 in toFixed
).replace(/^(-?\d{1,3})((\d{3})*)(\.\d+)?$/, function(all, first, subsequence, dmp, dec) { // Separate string into different parts
return (first || '') + subsequence.replace(/(\d{3})/g, ts + '$1') + (dec || ''); // Add thousands separator and rejoin all parts
} );
}