如何在JavaScript中将数字格式化为美元货币字符串?
我想用JavaScript格式化价格。
我想要一个以float
作为参数并返回如下格式的'string'的函数:
"$ 2,500.00"
最好的方法是什么?
解决方案
主要部分是插入千位分隔符,可以这样完成:
<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,","); 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)));">
我们可以使用:
var profits=2489.8237 profits.toFixed(3) //returns 2489.824 (round up) profits.toFixed(2) //returns 2489.82 profits.toFixed(7) //returns 2489.8237000 (padding)
然后,我们可以添加符号" $"。
如果我们需要','为千,我们可以使用:
Number.prototype.formatMoney = function(c, d, t){ var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "." : d, t = t == undefined ? "," : t, s = n < 0 ? "-" : "", i = String(parseInt(n = Math.abs(Number(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, "" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); };
并用于:
(123456789.12345).formatMoney(2, '.', ',');
如果我们总是要使用'。和',',我们可以将它们保留在方法调用之外,该方法将为我们默认它们。
(123456789.12345).formatMoney(2);
如果文化中有两个符号被翻转(即欧洲人),则只需将以下两行粘贴到formatMoney
方法中:
d = d == undefined ? "," : d, t = t == undefined ? "." : t,
查看JavaScript Number对象,看看它是否可以为我们提供帮助。
- toLocaleString()将使用特定于位置的千位分隔符格式化数字。
- " toFixed()"会将数字四舍五入到特定的小数位数。
要同时使用它们,必须将值的类型改回数字,因为它们都输出字符串。
例子:
Number(someNumber.toFixed(1)).toLocaleString()
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; }
来自WillMaster。
YUI代码库使用以下格式:
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 unaltered else { return nData; } }
由于YUI库是可配置的,因此需要进行编辑,例如将oConfig.decimalSeparator替换为""。
好的,根据发言,我正在使用此功能:
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;
我乐于接受改进建议(我不愿意仅仅为了做到这一点就不包括YUI :))
我已经知道我应该检测到"。"而不只是将其用作小数点分隔符...
符合原始要求的简约方法:
function formatMoney(n) { return "$ " + (Math.round(n * 100) / 100).toLocaleString(); }
@Daniel Magliola:没错,以上只是草率,不完整的实现。这是更正的实现:
function formatMoney(n) { return "$ " + n.toLocaleString().split(".")[0] + "." + n.toFixed(2).split(".")[1]; }
PHP函数" number_format"有一个javascript端口。
我发现它非常有用,因为它对于PHP开发人员来说易于使用且易于识别。
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 IE 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+''); 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; }
(原始注释块,下面包括示例,并在适当的位置注明)
// 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(别名Daok)代码,其中添加了一些注释和一些小的更改:
/* decimal_sep: character used as deciaml separtor, 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 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, "" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); }
这里是一些测试:
//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));
较小的更改是:
- 移动了Math.abs(decimals)一点,仅当不是NaN时才执行。
decimal_sep
不能再为空字符串(某种十进制分隔符是必须的)- 我们使用"如何最好地确定是否未将参数发送给JavaScript函数"中建议的`typeof Millennium_Sep ==='undefined'
- 不需要
(+ n || 0)
,因为this
是Number
对象
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 - IE also puts in .00, so we'll get 12,345,678.00 //if IE (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));
这适用于FF和IE
通常,有多种方法可以执行相同的操作,但是我会避免使用Number.prototype.toLocaleString
,因为它可以根据用户设置返回不同的值。
我也不建议扩展Number.prototype扩展本机对象原型是一种不好的做法,因为它可能导致与其他人代码(例如库/框架/插件)发生冲突,并且可能与将来的JavaScript实现/版本不兼容。
我相信正则表达式是解决该问题的最佳方法,这是我的实现:
/** * 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 [], middle [] and decimal digits [] 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); } }
于2010/08/30修改:添加了用于设置小数位数的选项。
在2011/08/23上编辑:添加了将小数位数设置为零的选项。