乐闻世界logo
搜索文章和话题

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

7 个月前提问
3 个月前修改
浏览次数106

6个答案

1
2
3
4
5
6

要将数字格式化为货币字符串,我们通常会遵循以下步骤:

  1. 确定货币单位:首先要决定使用哪种货币单位,比如美元(USD)、欧元(EUR)等,因为每种货币的格式可能有所不同。

  2. 小数点精度:货币通常需要保留两位小数,即分为单位。

  3. 千分位分隔符:大数额通常会使用逗号(在某些国家为点)作为千分位分隔符。

  4. 货币符号:根据货币的不同,可能会在前面或后面添加货币符号,比如'$'表示美元。

  5. 负数的表示:如果数额是负的,可以通过括号或者负号来表示。

举个例子,如果我们要将数字1234567.89格式化为美元字符串,我们会这样做:

  • 确定货币单位:美元($)
  • 小数点精度:保留两位小数,即".89"
  • 千分位分隔符:使用逗号将数字分隔为千分位,即"1,234,567.89"
  • 货币符号:在数额前加上美元符号,即"$1,234,567.89"
  • 负数的表示:如果是负数,写作"-$1,234,567.89"或"($1,234,567.89)"

在编程中,这可以通过各种方式实现,例如在JavaScript中,我们可以使用Intl.NumberFormat对象来格式化货币:

javascript
const number = 1234567.89; const formatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }); const formatted = formatter.format(number); // "$1,234,567.89"

在Python中,我们可以使用内置的locale模块或者第三方库如Babel来实现相同的功能:

python
import locale locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') number = 1234567.89 formatted = locale.currency(number, grouping=True) # "$1,234,567.89"

这些方法都可以实现将数字格式化为货币字符串的目的,并且可以根据不同的地区设置进行定制。

2024年6月29日 12:07 回复

国际数字格式

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

shell
// Create our number formatter. const formatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', // These options are needed to round to whole numbers if that's what you want. //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1) //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501) }); console.log(formatter.format(2500)); /* $2,500.00 */

运行代码片段Hide results

展开片段

使用系统区域undefined设置代替第一个参数('en-US'在示例中)(如果代码在浏览器中运行,则为用户区域设置)。区域设置代码的进一步解释

这是货币代码的列表

Intl.NumberFormat 与 Number.prototype.toLocaleString

最后一点是将其与旧版本进行比较。toLocaleString。它们都提供本质上相同的功能。然而,toLocaleString 的旧版本(Intl 之前)实际上并不支持语言环境:它使用系统语言环境。因此,在调试旧浏览器时,请确保您使用的是正确的版本(MDN 建议检查 是否存在Intl)。如果您不关心旧浏览器或只使用shim,则根本无需担心这一点。

_此外,对于单个_项目来说,两者的性能是相同的,但如果您有很多数字需要格式化,那么使用速度Intl.NumberFormat会快大约 70 倍。因此,通常最好Intl.NumberFormat在每次页面加载时仅使用和实例化一次。无论如何,这是等效的用法toLocaleString

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

运行代码片段Hide results

展开片段

关于浏览器支持和 Node.js 的一些说明

2024年6月29日 12:07 回复

Number.prototype.toFixed

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

shell
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)),您将获得美元金额。

自定义功能

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

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

运行代码片段Hide results

展开片段

像这样使用它:

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

如果您总是要使用“.”和“,”,您可以将它们从方法调用中删除,该方法将为您默认它们。

shell
(123456789.12345).formatMoney(2);

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

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

自定义函数(ES6)

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

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

运行代码片段Hide results

展开片段

2024年6月29日 12:07 回复

简短而快速的解决方案(适用于任何地方!)

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

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

测试:

shell
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]

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


超长短解

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

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

2024年6月29日 12:07 回复

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

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

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

例子:

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

编辑

可以直接使用 toLocaleString ,不需要重新转换为数字:

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

多个号码

如果您需要经常类似地格式化数字,您可以创建一个特定的对象以供重用。就像德语(瑞士):

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

可以用作:

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

相当漂亮。

2024年6月29日 12:07 回复

以下是Patrick Desjardins(别名 Daok)的代码,添加了一些注释和一些细微的更改:

shell
/* 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) : ''); }

这里有一些测试:

shell
// 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. 我们按照如何最好地确定参数是否未发送到 JavaScript 函数中的typeof thousands_sep === 'undefined'建议使用

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

JSFiddle

2024年6月29日 12:07 回复

你的答案