如何将数字格式化为货币字符串?


1841

我想用JavaScript格式化价格。我想要一个以a float作为参数并返回如下string格式的函数:

"$ 2,500.00"

最好的方法是什么?


8
formatNumberjavascript中没有内置函数
zerkms 2012年

500
请任何人在将来读这篇文章,也没有使用float存储货币。您将失去精度和数据。您应该将其存储为整数美分(或几美分等),然后在输出之前进行转换。
菲利普·怀特豪斯

8
@ user1308743浮点数不存储小数位。它使用值,基数和偏移量存储数字。0.01实际上无法表示。参见:en.wikipedia.org/wiki/Floating_point#Accuracy_problems
菲利普·怀特豪斯

6
@ user1308743:假设您代表了一个非常大的数字(假设您是个幸运儿,那是您的银行帐户余额)。您是否真的会因为精度不足而浪费钱?
ereOn 2012年

163
那么,为什么没有人建议以下内容?(2500).toLocaleString( “EN-GB”,{作风: “货币”,货币: “英镑”,minimumFractionDigits:2})developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
尼克·格莱利(Nick Grealy)2013年

Answers:


1789

Number.prototype.toFixed

该解决方案与每个主流浏览器兼容:

  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)

您所需要的只是添加货币符号(例如"$" + profits.toFixed(2)),您将有多少美元。

自定义功能

如果需要,在每个数字之间使用,则可以使用此功能:

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>

像这样使用它:

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

如果您总是要使用'。和',',您可以将它们保留在方法调用之外,该方法将为您默认它们。

(123456789.12345).formatMoney(2);

如果您的文化中有两个翻转的符号(即欧洲人),并且您想使用默认设置,只需将以下两行粘贴到formatMoney方法中:

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

自定义功能(ES6)

如果可以使用现代ECMAScript语法(即通过Babel),则可以改用以下更简单的函数:

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>


26
首先,出色,简洁的代码。但是,如果你是美国人,你应该改变的默认设置d,并t.,分别,这样你就不必每次都指定它们。另外,我建议将return语句的开头修改为:return s + '$' + [rest],否则您将不会获得美元符号。
杰森

744
不知道为什么人们认为这段代码很漂亮。这是难以理解的。看起来效果不错,但它并不漂亮。
usr

86
这个formatMoney函数是否是从某些缩小的JavaScript代码中复制的?您不能张贴原件吗?变量c,d,i,j,n,s和t代表什么?从这篇文章的评论和评论数量来看,我可以假设这段代码已经被复制粘贴到了生产网站的各个地方……如果有一天有错误,请维护代码!
zuallauz 2012年

259
“诗歌”?更像晦涩难懂。这不是高尔夫代码。使用一点空白。正确的var名称也不会受到损害。
keithjgrant 2012年


1510

国际数字格式

JavaScript具有数字格式化程序(国际化API的一部分)。

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

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

JS小提琴

使用undefined在适当位置的第一个参数(的'en-US'中的例子)使用系统区域(在情况下,代码在浏览器中运行的用户环境)。语言环境代码的进一步说明

这是货币代码列表

Intl.NumberFormat与Number.prototype.toLocaleString

最后一点,将其与旧版本进行比较。toLocaleString。它们都提供基本相同的功能。但是,toLocaleString的较旧版本(国际化之前)实际上不支持语言环境:它使用系统语言环境。因此,请确保您使用的版本正确(MDN建议检查是否存在Intl)。同样,对于单个项目,两者的性能是相同的,但是如果要格式化的数字很多,则使用Intl.NumberFormat速度将提高约70倍。使用方法toLocaleString如下:

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

有关浏览器支持的一些说明

  • 如今,浏览器支持已不再是一个问题,全球的支持率为97.5%,美国为98%,欧盟为99%
  • 垫片,以支持它的化石的浏览器(如IE8),你应该真正需要
  • 看看CanIUse了解更多信息

89
这个idomatic JavaScript,简单而优雅的解决方案正是我想要的。
Guilhem Soulas '02

9
投票给这个人是因为这是一个愚蠢的简单答案,它本机有效。
特拉西瓦'16

17
可以肯定的是,现在有相当多的浏览器支持此功能。这应该更多。
flq 2016年

2
这是一个很好的答案,我让它使用动态货币值,因此如果在欧洲使用,它将更改为EUR并显示欧元符号。工作请客!
Sprose

3
现在是2018年,基本上所有地方都支持。这应该是正确的答案。

1338

快速简便的解决方案(无处不在!)

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

该解决方案的思想是将匹配的部分替换为第一个匹配项和逗号,即'$&,'。匹配使用超前方法完成。您可以将表达式读为 “如果匹配数字,则后跟三个数字集(一个或多个)和一个点的序列”

测试:

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"

演示: http : //jsfiddle.net/hAfMM/9571/


扩展的短期解决方案

您还可以扩展Number对象的原型,以添加对任何小数位数[0 .. n]和数字组大小的附加支持[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"

演示/测试: http : //jsfiddle.net/hAfMM/435/


超级扩展短解决方案

在此超级扩展版本中,您可以设置不同的定界符类型:

/**
 * 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"

演示/测试: http : //jsfiddle.net/hAfMM/612/


21
实际上,我进一步走了一步:.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")
kalisjoshua

4
带有VisioN和kalisjoshua正则表达式的CoffeeScript版本以及指定小数位的方式(因此,您可以保留默认值2或为无小数位指定0):Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Eric Anderson

11
@Abbas是的,替换\.$(行尾),即this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,")
2013年

2
@hanumant这里的正则语法有点复杂,因此我建议您首先阅读有关正则表达式的手册(例如,在MDN)。其背后的想法是将匹配的部分替换为第一个匹配项和逗号,即$1,。匹配使用超前方法完成。您可以将表达式读为“如果匹配数字,则后跟三个数字集(一个或多个)和一个点的序列”
2013年

2
@JuliendePrabère请举一个长整数的示例,该方法不适用于这种方法。
2014年

247

查看JavaScript Number对象,看看它是否可以帮助您。

  • toLocaleString() 将使用特定于位置的千位分隔符格式化数字。
  • toFixed() 将数字四舍五入到特定的小数位数。

要同时使用它们,必须将值的类型改回数字,因为它们都输出字符串。

例:

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

2
谢谢!基于这个想法,我得以制作出简短而又简单的作品!(和本地化)优秀。
Daniel Magliola

7
其实可以。即对于美元:'$'+(value + 0.001).toLocaleString()。slice(0,-1)
Zaptree

6
看起来不错,但目前几乎没有浏览器支持
acorncom 2013年

1
@acorncom为什么您说“很少支持浏览器”?自Javascript 1.1起,Number对象就存在了。请提供支持您的主张的参考。
Doug S

2
请注意,有一个toLocaleString使用系统语言环境的旧版本,以及一个来自ECMAScript Intl API的新版本(不兼容)。在这里解释。这个答案似乎是针对旧版本的。
aross

162

以下是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 [/programming/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) : ''); 
}

这里是一些测试:

//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));

较小的更改是:

  1. Math.abs(decimals)只在没有移动时才做一点动作NaN

  2. decimal_sep 不能再为空字符串(必须使用某种十进制分隔符)

  3. 我们typeof thousands_sep === 'undefined'按照如何最佳确定是否未将参数发送给JavaScript函数中的建议进行使用

  4. (+n || 0)不需要,因为它this是一个Number对象

JS小提琴


8
您可能想在parseInt中使用“ 10”作为基数。否则,任何以“ 0”开头的数字都将使用八进制编号。
sohtimsso1970 2011年

3
@ sohtimsso1970:很抱歉收到您的回复,但是您能再解释一下吗?我看不到数字可以解释为八进制的地方。在parseInt被称为对数的整数部分的绝对值。除非只是零,否则INTEGER部分不能以零开始!而parseInt(0) === 0无论是八进制或十进制。
Marco Demaio,2012年

例如,尝试:parseInt(“ 016”)...返回14,因为当字符串以零开头时,parseInt假定它是八进制编码的。
Tracker1 2012年

4
@ Tracker1:我知道以开头的数字0被视为八进制parseInt。但是在此代码中,不可能parseInt接收016作为输入(或任何其他八进制格式的值)的输入,因为传递给的参数parseIntMath.abs函数的第一个处理。因此,没有办法parseInt接收以零开头的数字,除非它只是零或0.nn(其中nn是小数)。但是00.nn字符串都将被转换parseInt为假定的纯零。
Marco Demaio 2012年

该函数不正确:>(2030).toMoney(0,'。',''); <“ 2 03 0”
Anton P Robul

124

accounting.js是一个小型的JavaScript库,用于数字,货币和货币格式设置。


...只要记住要传递一个货币符号,否则它会在IE7和IE8中出错,无论哪种方式IE9都可以
矢量“

2
看起来IE7 / IE8错误已修复。
Mat Schaffer 2012年

2
这是一个很棒的库,能够传递货币符号也是一个好主意,因为所有货币详细信息都包含在单个函数调用/设置中
farinspace 2012年

2
我喜欢这样的事实,您可以做相反的事情-传递格式化的货币字符串并获取数值。
尼尔·门罗2014年

2
accounting.js似乎最近没有维护。带有最新更改的一个分支是github.com/nashdot/accounting-js
RationalDev喜欢GoFundMonica

124

如果数量是数字,请说-123,然后

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

将产生字符串 "-$123.00"

这是一个完整的工作示例


7
这个答案对我来说差不多了,但是我需要将它四舍五入到最接近的一分钱。这是我使用的amount.toLocaleString('en-GB',{style:'currency',currency:'GBP',maximumFractionDigits:2});
Nico 2014年

上面的代码会四舍五入为所需的位数。请参阅示例,然后在输入框中输入1.237。
丹尼尔·巴拉巴拉斯

3
在Safari中似乎不起作用。它只是以数字形式返回数字,而没有任何格式。
兰斯·安德森

1
哇,这是一个非常好的答案。应该在最前面。
伊桑(Ethan)

2
如果出于某些原因您不希望使用美分,则可以使用以下方式更改小数精度:minimumFractionDigits: 0
Horacio

99

这是我见过的最好的js货币格式化程序:

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) : "");
};

它已重新格式化并从这里借来:https : //stackoverflow.com/a/149099/751484

您必须提供自己的货币标记(您在上面使用了$)。

像这样调用它(尽管请注意,args默认为2,逗号和&,所以如果您愿意的话,您不需要提供任何args):

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

当心

6
@hacklikecrack,所有变量都是局部变量;他们在var声明中。
Jonathan M

3
抱歉,是的,尽管您要重新声明参数。缩进!;)
hacklikecrack

可怕地使用了变量名!
Serj Sagan

77

这里已经有一些不错的答案。这是另一种尝试,只是为了好玩:

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

和一些测试:

formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"

编辑:现在它将处理负数


诗歌。辉煌。您是否尝试过reduceRight()developer.mozilla.org/zh-CN/JavaScript/Reference/Global_Objects / ...应该消除reverse()吗?
史蒂夫

1
@Steve-对,但是您需要i = orig.length - i - 1在回调中执行类似的操作。尽管如此,数组的遍历也要少一些。
韦恩

11
一个关于兼容性的问题:该reduce方法在Ecmascript 1.8中引入,在Internet Explorer 8及以下版本中不支持。
布莱斯

就像@Blaise所说的那样,此方法在IE 8或更低版本中将不起作用。
rsbarro

是的,那是正确的。正如答案本身所指出的,这只是为了好玩。同样,它应该处理负数也很好。
韦恩(Wayne)

76

适用于所有当前浏览器

用于toLocaleString以语言敏感的形式格式化货币(使用ISO 4217货币代码)。

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

@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


1
因为只有少数浏览器(例如Chrome 24,IE11和Opera 15)才支持“语言环境”和“选项”参数,但Firefox,Safari和其他旧版本仍不支持。
VisioN

3
同意,尚未在所有浏览器中完全支持它,但仍然是一种解决方案。(而且可以说是最有效的解决方案,因为它与不受支持的浏览器向前兼容,并且是Javascript API的文档功能。)
Nick Grealy

1
我很喜欢,很高兴它可以与印度数字分组一起使用。
MSC

7
截至2017年,这已得到完全支持,应该是唯一的正确答案
Evgeny

1
最新和最好的:) FF69,Chrome76等。此处不使用“ R 2 500,00”,它应为“ R 2,500.00”,与en-GB相同。
avenmore

70

我想你想要的是 f.nettotal.value = "$" + showValue.toFixed(2);


@暗恋此方法有效,但它不再将计算结果带入税收领域?
Rocco The Taco 2012年

11
将$符号附加到它之后,它不再是数字,而是字符串。
暗恋

此选项不会在数千之间加逗号。:-(
Simon East


27

好的,根据您的发言,我正在使用此功能:

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 :))我已经知道我应该检测到“。” 而不只是将其用作小数点分隔符...


8
请注意,您的版本未正确舍入为两位小数。例如,3.706的格式应为“£3.70”,而不是应为的“£3.71”。
Ates Goral

是的,在我的具体情况确定,因为数额我的工作已经有最多2个位数,我需要修复到2位小数的原因是没有小数或只有1数额
丹尼尔Magliola

26

我使用全球化图书馆(来自Microsoft):

这是一个很棒的项目,可以对数字,货币和日期进行本地化,并根据用户区域设置以正确的方式自动格式化它们!...尽管应该是jQuery扩展,但目前是100%独立的库。我建议大家尝试一下!:)


3
哇,为什么还不赞成呢?大型标准化库,可进行各种格式设置。具有正确全球化的行业标准格式设置参数。好答案!
pbarranis

它仍然被认为是Alpha阶段,因此请谨慎使用,但发现的很好。
尼尔·门罗2014年

1
不再处于Alpha(或Beta)状态。这在我们等待Safari满足新标准并让IE <11消失时非常有用。
Guy Schalnat 2015年

25

javascript-number-formatter(以前为Google Code

  • 简短,快速,灵活但独立。 仅75行,包括MIT许可证信息,空白行和注释。
  • 接受类似#,##0.00或带否定的标准数字格式-000.####
  • 接受像任何国家的格式# ##0,00#,###.###'###.##或任何类型的非编号的象征。
  • 接受任意数量的数字分组。#,##,#0.000#,###0.##全部有效。
  • 接受任何冗余/安全格式。##,###,##.#还是0#,#00#.###0#都OK。
  • 自动四舍五入。
  • 简单的界面,只需提供以下掩码和值即可:format( "0.0000", 3.141592)
  • 在掩码中包含前缀和后缀

(摘自其自述文件)


23

+1代表乔纳森(Jonathan M)提供了原始方法。由于这显然是货币格式化程序,因此我继续将货币符号(默认为'$')添加到输出中,并添加了默认逗号作为千位分隔符。如果您实际上不需要货币符号(或千位分隔符),则只需使用“”(空字符串)作为参数即可。

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) : "");
};

第一个var有点奇怪,因为这些变量已在函数声明中声明。除此之外,谢谢!
Rich Bradshaw

2
你是对的。这是我从乔纳森·M(Jonathan M)的原始作品中引入的一个错误,在这些作品中它们都被链接为一个var表达式。这些应该是简单的任务。定影。
XML

就此而言,我认为这可能是过早优化的,应该对其进行重构以提高可读性。但是我的目标是增加OP的代码,而不是从根本上改变它。
XML

还算不错,这+n || 0是唯一看起来有点奇怪的东西(无论如何对我来说)。
Rich Bradshaw

2
this是一个非常有用的变量名。将其转换为,n以便在定义时间保存3个字符,这在RAM和带宽以KB为单位的时代中可能是必要的,但是在minifier在产品投入生产之前会处理所有事情的时代中,这只是模糊的。其他巧妙的微优化至少值得商bat。
XML

22

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+'$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; 
}

原始注释栏,下面包括示例,并在适当的位置注明)

// 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'

这只是一个正确的函数:> number_format(2030,0,'。','')<'2 030'棒极了!谢谢
Anton P Robul

21

带正则表达式的较短方法(用于插入空格,逗号或点)?

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

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

20

还没有看到这样的东西。非常简洁,易于理解。

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

这是一个在最终输出中具有更多选项的版本,允许以不同的地区格式设置不同的货币格式。

// 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)
)


很棒的代码段,谢谢。但是,请小心,因为它在IE上不起作用,因为不支持默认参数,并且<IE11中不支持“ const”和“ let”。可以用以下方法解决:+ moneyFormat:函数(价格,符号){+ if(!sign)sign ='$'; +片段= parseFloat(price).toFixed(2).split('')+ var ii =片段。长度-3
Charlie Dalsass

不用担心@CharlieDalsass。我建议使用babel将其编译到ES5以生产代码。
synthet1c

但是怎么做欧元货币呢?1.000,00欧元?

@YumYumYum我添加了一个完整的示例,其中包含更多格式选项,以提供更大的灵活性。
synthet1c

18

Patrick Desjardins的回答看起来不错,但我更喜欢简单的JavaScript。这是我刚刚编写的用于接受数字并以货币格式(减去美元符号)返回的函数

// 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];
}

我需要在浏览器和旧版本的Node中都能工作。这工作得很好。谢谢
n8jadams

17

主要部分是插入千位分隔符,可以这样完成:

<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)));">

在ins1000Sep()中输入负值时,我得到了错误的数字输出。
彼得

16

有一个内置的function toFixedjavascript

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

这个答案看起来多余。Crush的答案已经受到关注-Ian toFixed()
Dunn

3
toFixed()Number对象的函数,var num如果是则无法使用String,因此附加上下文对我有所帮助。
timborden 2012年

15
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


小而简单。谢谢。
康纳·辛普森

1
简单,但没有逗号1,000
aron

15

我建议使用Google Visualization API中的NumberFormat类

您可以执行以下操作:

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

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

希望对您有所帮助。


14

这可能有点晚了,但是这是我刚刚为同事设计的一种.toCurrencyString()向所有数字添加语言环境感知功能的方法。内部化仅用于数字分组,而不用于货币符号-如果您输出的是美元,请"$"按提供的方式使用,因为$123 4567在日本或中国,美元数量$1,234,567与美国的数量相同。如果您要输出欧元/等,则将货币符号从"$"

在需要使用它之前,请将其声明在HEAD中的任何位置或任何需要的地方:

  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;
  }

这样就完成了!(number).toCurrencyString()在需要将数字输出为货币的任何地方使用。

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

12

通常,有多种方法可以执行相同的操作,但是我会避免使用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 [$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);
    }
}

于2010/08/30修改:添加了用于设置小数位数的选项。 在2011/08/23上编辑:添加了将小数位数设置为零的选项。


toLocaleString的要点是它会根据用户的设置进行调整。
2013年

11

以下是一些解决方案,都通过了测试套件,测试套件和基准测试,如果您想复制和粘贴进行测试,请尝试 This Gist

方法0(RegExp)

基于https://stackoverflow.com/a/14428340/1877620,但如果没有小数点,则进行修复。

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('.');
    };
}

方法2(拆分为数组)

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('.');
    };
}

方法3(循环)

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));
}

分隔器

如果要自定义千位分隔符或十进制分隔符,请使用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, 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();

从方法2进行了改进。从var a = this.toFixed(precision).split('。')更改为var乘数= Math.pow(10,precision + 1),WholeNumber = Math.floor(this * multiplier) ; var a = Math.round(WholeNumber / 10)* 10 /乘数;如果(String(a).indexOf('。')<1){a + ='.00'; } a = String(a).split('。'),请勿使用toFixed,因为它有问题。
vee 2014年

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所有这些值的小数应为.84而不是.83
vee


10

一个简单的选项,可以通过反转字符串first和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();
};

10

我是从以下帐户中找到的:accounting.js。它非常简单,非常适合我的需求。

// 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€ 


$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );-显示1.000,00 E
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.