ChatGPT解决这个技术问题 Extra ChatGPT

如何在 JavaScript 中用逗号打印一个数字作为千位分隔符

我试图用逗号作为千位分隔符在 JavaScript 中打印一个整数。例如,我想将数字 1234567 显示为“1,234,567”。我该怎么做呢?

这是我的做法:

function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

有没有更简单或更优雅的方法来做到这一点?如果它也适用于浮点数会很好,但这不是必需的。在句点和逗号之间决定不需要特定于语言环境。

Number(x).toLocaleString()
值得注意的是,在 2016 中,Number.prototype.toLocaleString still 在 Safari 中不起作用。而不是实际格式化数字,它只是返回它,没有抛出错误。因此,今天拥有最大的脸...#goodworkApple
@atomless 真的吗?我有 Version 61.0.3163.100 (Official Build) (64-bit),当我说 (2982932323).toLocaleString() 时,响应是 "2,982,932,323"。我的默认语言环境是 en-US。也许你应该试试 (2982932323).toLocaleString('en-US')
似乎这应该是批准的答案... Intl.NumberFormat('en-US').format(count) 见 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Number.prototype.toLocaleString 于 2021 年在 Safari 14 中运行。

A
Aryan Beezadhur

我使用了 Kerry 回答中的想法,但简化了它,因为我只是为我的特定目的寻找简单的东西。这是我所拥有的:

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

函数 numberWithCommas(x) { return x.toString().replace(/\B(?"} ${x} => ${result}`);回程通行证; } 让失败 = 0;失败 += !test(0, "0");失败 += !test(100, "100");失败 += !test(1000, "1,000");失败 += !test(10000, "10,000");失败 += !test(100000, "100,000");失败 += !test(1000000, "1,000,000");失败 += !test(10000000, "10,000,000"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("所有测试通过"); } .as-console-wrapper { max-height: 100% !important; }

正则表达式使用 2 个前瞻断言:

一个正数,用于查找字符串中后面连续有 3 个数字的倍数的任何点,

一个否定断言,以确保该点仅具有 3 位数字的倍数。替换表达式在此处放置一个逗号。

例如,如果您传递 123456789.01,则肯定断言将匹配 7 左侧的每个点(因为 789 是 3 位的倍数,678 是 3 位的倍数,567, ETC。)。否定断言检查 3 位的倍数后面没有任何数字。 789 后面有一个句点,所以它正好是 3 位数字的倍数,所以用逗号。 678 是 3 位数字的倍数,但它后面有一个 9,所以这 3 位数字是 4 组的一部分,逗号不会出现在那里。 567 也是如此。 456789 是 6 位数字,是 3 的倍数,所以在它前面加逗号。 345678 是 3 的倍数,但它后面有一个 9,所以那里没有逗号。等等。 \B 防止正则表达式在字符串的开头放置逗号。

@neu-rah 提到如果小数点后超过 3 位,此函数会在不需要的位置添加逗号。如果这是一个问题,您可以使用此功能:

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

函数 numberWithCommas(x) { var parts = x.toString().split(".");部分[0] = 部分[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");返回parts.join("."); } 函数测试(x,期望){ 常量结果 = numberWithCommas(x);常量传递=结果===期望; console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`);回程通行证; } 让失败 = 0;失败 += !test(0 , "0");失败 += !test(0.123456 , "0.123456");失败 += !test(100 , "100");失败 += !test(100.123456 , "100.123456");失败 += !test(1000 , "1,000");失败 += !test(1000.123456 , "1,000.123456");失败 += !test(10000 , "10,000");失败 += !test(10000.123456 , "10,000.123456");失败 += !test(100000 , "100,000");失败 += !test(100000.123456 , "100,000.123456");失败 += !test(1000000 , "1,000,000");失败 += !test(1000000.123456 , "1,000,000.123456");失败 += !test(10000000 , "10,000,000");失败 += !test(10000000.123456, "10,000,000.123456"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("所有测试通过"); } .as-console-wrapper { max-height: 100% !important; }

@t.j.crowder 指出,既然 JavaScript 有lookbehind (support info),它可以在正则表达式本身中解决:

function numberWithCommas(x) {
    return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}

函数 numberWithCommas(x) { return x.toString().replace(/\B(?"} ${x} => ${result}`);回程通行证; } 让失败 = 0;失败 += !test(0, "0");失败 += !test(0.123456, "0.123456");失败 += !test(100, "100");失败 += !test(100.123456, "100.123456");失败 += !test(1000, "1,000");失败 += !test(1000.123456, "1,000.123456");失败 += !test(10000, "10,000");失败 += !test(10000.123456, "10,000.123456");失败 += !test(100000, "100,000");失败 += !test(100000.123456, "100,000.123456");失败 += !test(1000000, "1,000,000");失败 += !test(1000000.123456, "1,000,000.123456");失败 += !test(10000000, "10,000,000");失败 += !test(10000000.123456, "10,000,000.123456"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("所有测试通过"); } .as-console-wrapper { max-height: 100% !important; }

(?<!\.\d*) 是一个否定的lookbehind,表示匹配项前面不能有 . 后跟零个或多个数字。至少在 V8 中,负后视比 splitjoin 解决方案 (comparison) 更快。


非常酷,确实注意到它在小数点后超过 3 位的数字存在问题。
试试 numberWithCommas(12345.6789) -> "12,345.6,789" 我不喜欢
在“。”之后修复的小改进问题 '123456789.01234'.replace(/\B(?=(?=\d*\.)(\d{3})+(?!\d))/g, '_')
@DmitrijGolubev 不适用于整数。也许强制小数点将是解决方案。
这在 Safari 中不起作用。破坏了我的整个应用程序并让我永远弄清楚这是问题所在
H
HoldOffHunger

我很惊讶没有人提到 Number.prototype.toLocaleString。它是在 JavaScript 1.5(于 1999 年推出)中实现的,因此基本上所有主流浏览器都支持它。

变量 n = 34523453.345; console.log(n.toLocaleString()); // "34,523,453.345"

从 v0.12 开始,它也可以通过包含 Intl 在 Node.js 中使用

如果您想要不同的东西,Numeral.js 可能会很有趣。


@csigrist 好点,但并不像看起来那么糟糕。速度取决于浏览器。在 FF 或 Opera 中表现良好。不过我很讨厌 Chrome。至于零:var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00" 这些选项在 FF 或 Safari 中不起作用。
性能差异可能是也可能不是问题,具体取决于上下文。如果用于包含 1000 个结果的巨型表格,那么它会更重要,但如果仅用于单个值,则差异可以忽略不计。但优点是它可以感知区域设置,因此欧洲的某些人会看到 34.523.453,345 或 34 523 453,345。这在一个有来自许多国家的访问者的网站上更为重要。
惊人的。最后一个带有本机功能的答案。更重要的是,这个在不同的国家用不同的分隔符正确显示(在捷克共和国我们写 X XXX XXX,YYY)。
googlers 更新:从 v0.12 开始,toLocaleString 通过 inclusion of Intl 在 Node.js 中工作。
@MSC,您应该改用 parseInt("1234567", 10).toLocaleString('en-US', {minimumFractionDigits: 2})new Number("1234567").toLocaleString('en-US', {minimumFractionDigits: 2})。它不起作用,因为您在字符串而不是数字上使用它。
v
vsync

下面是两种不同的浏览器 API,它们可以将 Numbers 转换为结构化的Strings。请记住,并非所有用户的计算机都有 locale that uses commas in numbers。要在输出中强制使用逗号,可以使用任何“西方”locale,例如 en-US

let number = 1234567890; // Example number to be converted

⚠️ 请注意 javascript 的 maximum integer 值为 9007199254740991

toLocaleString

// default behaviour on a machine with a local that uses commas for numbers
let number = 1234567890;
number.toLocaleString(); // "1,234,567,890"

// With custom settings, forcing a "US" locale to guarantee commas in output
let number2 = 1234.56789; // floating point example
number2.toLocaleString('en-US', {maximumFractionDigits:2}) // "1,234.57"

数字格式

let number = 1234567890;
let nf = new Intl.NumberFormat('en-US');
nf.format(number); // "1,234,567,890"

根据我的检查(至少是 Firefox),它们在性能方面或多或少是相同的。

现场演示https://codepen.io/vsync/pen/MWjdbgL?editors=1000


浏览器支持总是在我链接到的每个 MDN 页面的底部提到。
基本 toLocaleString 适用于 safari,选项不适用
正如其他人所指出的,number.toLocaleString 不适用于所有浏览器,也不适用于 PhantomJS。 Number.toLocaleString() doesn't apply appropriate formatting
toLocaleString 解决方案可能还应包括所需的语言环境,例如 toLocaleString("en"),因为英语模式使用逗号。但是,如果在法国运行没有语言环境指示符的 toLocaleString(),那么它将产生句点而不是逗号,因为这是用于在本地分隔数千个字符的方式。
还可以添加 minimumFractionDigits: 2 以确保固定的小数位数 stackoverflow.com/questions/31581011/…
T
T.J. Crowder

我建议使用 phpjs.org 的 number_format()

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   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)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     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'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

2014 年 2 月 13 日更新

人们一直在报告这没有按预期工作,所以我做了一个包含自动化测试的JS Fiddle

2017 年 11 月 26 日更新

这是作为堆栈片段的小提琴,输出略有修改:

function number_format(number, decimals, dec_point, crowd_sep) { // http://kevin.vanzonneveld.net // + 原作者:Jonas Raoni Soares Silva (http://www.jsfromhell.com) // + 改进: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + 修正:Michael White (http://getsprink.com) // + 修正:Benjamin Lupton // + 修正:Allan Jensen (http: //www.winternet.no) // + 修改者:Jonas Raoni Soares Silva (http://www.jsfromhell.com) // + 错误修复者:Howard Yeend // + 修改者:Luke Smith (http:// lucassmith.name) // + 修正者:Diogo Resende // + 修正者:竞争对手 // + 输入者:Kheang Hok Chin (http://www.distantia.ca/) // + 改进者:davook // +改进者:Brett Zamir (http://brett-zamir.me) // + 输入者:Jay Klehr // + 改进者:Brett Zamir (http://brett-zamir.me) // + 输入者:Amir Habibi (http://www.residence-mixte.com/) // + 修正错误:Brett Zamir (http://brett-zamir.me) // + 改进: Theriault // + 改进: Drew Noakes / / * 示例1:number_for垫子(1234.56); // * 返回 1: '1,235' // * 示例 2: number_format(1234.56, 2, ',', ' '); // * 返回 2: '1 234,56' // * 示例 3: number_format(1234.5678, 2, '.', ''); // * 返回 3: '1234.57' // * 示例 4: number_format(67, 2, ',', '.'); // * 返回 4: '67,00' // * 示例 5: number_format(1000); // * 返回 5: '1,000' // * 示例 6: number_format(67.311, 2); // * 返回 6: '67.31' // * 示例 7: number_format(1000.55, 1); // * 返回 7: '1,000.6' // * 示例 8: number_format(67000, 5, ',', '.'); // * 返回 8: '67.000,00000' // * 示例 9: number_format(0.9, 0); // * 返回 9: '1' // * 示例 10: number_format('1.20', 2); // * 返回 10: '1.20' // * 示例 11: number_format('1.20', 4); // * 返回 11: '1.2000' // * 示例 12: number_format('1.2000', 3); // * 返回 12: '1.200' var n = !isFinite(+number) ? 0 : +number, prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), sep = (typeof crowd_sep === 'undefined') ? ',' :数千个 sep, dec = (typeof dec_point === 'undefined') ? '。' : dec_point, toFixedFix = function (n, prec) { // 修复 IE parseFloat(0.55).toFixed(0) = 0; var k = Math.pow(10, prec);返回 Math.round(n * k) / k; }, s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.'); if (s[0].length > 3) { s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g,九月); } if ((s[1] || '').length < prec) { s[1] = s[1] || ''; s[1] += new Array(prec - s[1].length + 1).join('0'); } 返回 s.join(dec); } var exampleNumber = 1;函数测试(预期,数字,小数,dec_point,数千个sep){ var实际= number_format(数字,小数,dec_point,数千个sep); console.log( '测试用例 ' + exampleNumber + ': ' + '(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) + ', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' + ', crowd_sep: "' + (typeof crowd_sep === 'undefined' ? '(default)' : crowd_sep) + '")' ); console.log(' => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", 预期 "' + expected + '".');示例编号++; } 测试('1,235', 1234.56);测试('1 234,56', 1234.56, 2, ',', ' ');测试('1234.57', 1234.5678, 2, '.', ''); test('67,00', 67, 2, ',', '.');测试('1,000',1000);测试('67.31',67.311,2);测试('1,000.6', 1000.55, 1);测试('67.000,00000', 67000, 5, ',', '.');测试('1',0.9,0);测试('1.20','1.20',2);测试('1.2000','1.20',4);测试('1.200','1.2000',3); .as-console-wrapper { max-height: 100% !important; }


@Andrew S -- 只有 1 人已将其标记下来。它确实有效,我在自己的代码中多次使用它。它也不是我的代码(也不是我的测试),我引用了它来自的站点,这是一个知名站点。也许他们有它的更新版本)因为您正在查看的代码是 3 岁。
@ernix - 操作员要求使用 JavaScript,我给出的答案是 JavaScript。这是 PHP 函数的 JavaScript 解释。
@ernix - 它与OP给出的示例完全一样。我放了一个小提琴,所以你可以看到。
@ernix - 好的,但关键是它完全符合 OP 的要求。它来自另一个站点(不是由我维护的,我之前已经说过),并且在给它适当的变量时,它的工作原理与所述完全一致。如果您认为这是一个错误,请联系 phpjs.org 或查看他们是否有更新版本。
太棒了。我一直在寻找,只发现了非常臃肿的库,甚至不允许我更改千位和小数点分隔符。
u
user1437663

这是@mikez302 答案的变体,但经过修改以支持带小数的数字(根据@neu-rah 的反馈 numberWithCommas(12345.6789) -> "12,345.6,789" 而不是 "12,345.6789"

function numberWithCommas(n) {
    var parts=n.toString().split(".");
    return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}

T
Tutankhamen
function formatNumber (num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
}

print(formatNumber(2665));      // 2,665
print(formatNumber(102665));    // 102,665
print(formatNumber(111102665)); // 111,102,665

我的答案没有做什么?正则表达式看起来略有不同,但看起来应该做同样的事情。
这是优雅的。正是我想要的。
来自blog.tompawlak.org/number-currency-formatting-javascript?已知问题:formatNumber(0.123456) = 0.123,456 JS 中没有后视功能,很难用优雅的正则表达式修复它。
这允许像 abcdef 之类的字符......应该受到限制。
123456789.123456789.toString().replace(/(\d)(?=(\d{3})+\.)/g, '$1,') => 123,456,789.12345679
T
Tính Ngô Quang

使用正则表达式

function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(toCommas(123456789)); // 123,456,789

console.log(toCommas(1234567890)); // 1,234,567,890
console.log(toCommas(1234)); // 1,234

使用 toLocaleString()

var number = 123456.789;

// request a currency format
console.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));
// → 123.456,79 €

// the Japanese yen doesn't use a minor unit
console.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))
// → ¥123,457

// limit to three significant digits
console.log(number.toLocaleString('en-IN', { maximumSignificantDigits: 3 }));
// → 1,23,000

参考MDN:Number.prototype.toLocaleString()

使用 Intl.NumberFormat()

var number = 123456.789;

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
// expected output: "123.456,79 €"

// the Japanese yen doesn't use a minor unit
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
// expected output: "¥123,457"

// limit to three significant digits
console.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));

// expected output: "1,23,000"

参考Intl.NumberFormat

演示在这里



使用正则表达式

使用 toLocaleString()

使用 Intl.NumberFormat()

表现

https://i.stack.imgur.com/K9gnJ.png


如果您正在动态键入,这将不起作用。如果你只是给它一个值,它会起作用,但是如果你不断地动态地输入一个值,逗号就会被添加到错误的位置。
我已经更新了我的答案下面的演示。在文本框中输入动态值时。你试试@EdgarQuintero
货币格式严重扭曲了这一点:jsben.ch/u4gk0
D
Dustin Sun

Intl.NumberFormat

原生 JS 函数。受 IE11、Edge、最新的 Safari、Chrome、Firefox、Opera、iOS 上的 Safari 和 Android 上的 Chrome 支持。

var number = 3500;

console.log(new Intl.NumberFormat().format(number));
// → '3,500' if in US English locale

我的答案已根据您的评论进行了更新。谢谢!
J
Javier Elices

这个问题得到的答案数量给我留下了深刻的印象。我喜欢 uKolka 的回答:

n.toLocaleString()

但不幸的是,在西班牙语等某些语言环境中,对于低于 10,000 的数字,它无法正常工作(恕我直言):

Number(1000).toLocaleString('ES-es')

给出 1000 而不是 1.000

请参阅 toLocaleString not working on numbers less than 10000 in all browsers 了解原因。

所以我不得不使用 Elias Zamaria 的答案,选择正确的千位分隔符:

n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

对于使用 ,. 作为千位分隔符并在所有情况下从 1,000 开始工作的两种语言环境,这一行都适用。

Number(1000).toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

给出带有西班牙语言环境上下文的 1.000

如果您想完全控制数字的格式,您也可以尝试以下方法:

let number   = 1234.567
let decimals = 2
let decpoint = '.' // Or Number(0.1).toLocaleString().substring(1, 2)
let thousand = ',' // Or Number(10000).toLocaleString().substring(2, 3)

let n = Math.abs(number).toFixed(decimals).split('.')
n[0] = n[0].split('').reverse().map((c, i, a) =>
  i > 0 && i < a.length && i % 3 == 0 ? c + thousand : c
).reverse().join('')
let final = (Math.sign(number) < 0 ? '-' : '') + n.join(decpoint)

console.log(final)

给出 1,234.57

这个不需要正则表达式。它的工作原理是先用 toFixed 将数字调整为所需的小数位数,然后将其除以小数点 .(如果有小数点)。然后将左侧变成一个反转的数字数组。然后从一开始每三位数字添加一个千位分隔符,结果再次反转。最终的结果是两部分的结合。输入数字的符号首先用 Math.abs 删除,然后在必要时放回。

它不是单行的,但不会更长,而且很容易变成一个函数。为了清楚起见,添加了变量,但如果事先知道,这些变量可以用它们的期望值代替。您可以使用使用 toLocaleString 的表达式来找出当前区域设置的小数点和千位分隔符的正确字符(请记住,这些需要更现代的 Javascript。)


N
None

感谢大家的回复。我已经建立了一些答案,以制作更“一刀切”的解决方案。

第一个代码段向 Number 原型添加了一个模仿 PHPnumber_format() 的函数。如果我正在格式化数字,我通常需要小数位,因此该函数需要显示小数位数。一些国家使用逗号作为小数,使用小数作为千位分隔符,因此该函数允许设置这些分隔符。

Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.toFixed(decimals).split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);

    return parts.join(dec_point);
}

您可以按如下方式使用它:

var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

我发现我经常需要取回数字以进行数学运算,但 parseFloat 将 5,000 转换为 5,只需取第一个整数值序列。所以我创建了自己的浮点转换函数并将其添加到字符串原型中。

String.prototype.getFloat = function(dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.split(dec_point);
    var re = new RegExp("[" + thousands_sep + "]");
    parts[0] = parts[0].replace(re, '');

    return parseFloat(parts.join(dec_point));
}

现在您可以按如下方式使用这两个功能:

var foo = 5000;
var fooString = foo.numberFormat(2); // The string 5,000.00
var fooFloat = fooString.getFloat(); // The number 5000;

console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00

非常好,我借用了第一种方法;)但是当您想使用欧洲格式并且数字是小数时,它不会产生正确的结果。第 5 行应为:var parts = this.toFixed(decimals).toString().split('.');
你说的对! toFixed() 将逗号更改为句点,因此 '.'应使用而不是 var dec_point。感谢您指出了这一点。
你可以为此制作一个 npm 模块吗?
@J.Money .toString 是不必要的, toFixed 已经返回一个字符串。
我完全不知道您为什么在这里提到了 PHP,或者给出了一个已经exists的原型函数
b
bummi

我认为这是最短的正则表达式:

/\B(?=(\d{3})+\b)/g

"123456".replace(/\B(?=(\d{3})+\b)/g, ",")

我检查了几个数字,它起作用了。


仅当您在分隔符后没有超过 3 个数字的浮点数时才有效,在这种情况下为点。否则它也会添加一个逗号。 "1234567890.1234567890".replace(/\B(?=(\d{3})+\b)/g, ",") 例如,这不起作用。返回“1,234,567,890.1,234,567,890”
虽然适用于货币!在添加逗号之前将您的数字四舍五入。
它在小数点后添加: 12.3456".replace(/\B(?=(\d{3})+\b)/g, ",") == 12.3,456
S
Sinan

如果所有浏览器 (Safari) 都本机提供 Number.prototype.toLocaleString(),那就太棒了。

我检查了所有其他答案,但似乎没有人填充它。这是一个 poc,实际上是前两个答案的组合;如果 toLocaleString 有效,则使用它,如果无效,则使用自定义函数。

var putThousandsSeparators; putThousandsSeparators = function(value, sep) { if (sep == null) { sep = ','; } // 检查是否需要格式化 if (value.toString() === value.toLocaleString()) { // 拆分小数 var parts = value.toString().split('.') // 格式化整数部分[0] = 部分[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep); // 将它们重新组合在一起 value = parts[1] ? parts.join('.') : 部分[0]; } else { value = value.toLocaleString(); } 返回值; };警报(放置数千个分隔符(1234567.890));


请注意,polyfill 仅适用于最多包含 3 个小数的数字。例如:0.12345 将输出 0.12,345。可以在 underscore.string 中找到一个很好的实现
你是对的,在 if 条件下添加 value > 1000 可以修复这种情况,但这是一个 poc,当然可以在其他地方找到更好的测试版本,感谢您的指出。
放置 value > 1000 是不够的,因为它对于任何数字和超过 3 位小数都是相同的。例如 1000.12345 返回 1,000.12,345。你的答案很好,而且在正确的道路上,但只是不完整。我只是想指出可能偶然发现您的答案的其他人,并且只是复制/粘贴它而无需使用不同的输入数据进行测试。
好吧,这需要另一个编辑 :) 我同意,但现在至少它应该适用于大多数情况。
p
phette23

千位分隔符可以使用浏览器的 Intl 对象以国际友好的方式插入:

Intl.NumberFormat().format(1234);
// returns "1,234" if the user's locale is en_US, for example

有关更多信息,请参阅 MDN's article on NumberFormat,您可以指定语言环境行为或默认为用户的行为。这更简单一点,因为它尊重当地的差异;许多国家使用句点分隔数字,而逗号表示小数。

Intl.NumberFormat 尚未在所有浏览器中可用,但它适用于最新的 Chrome、Opera 和 IE。 Firefox 的下一个版本应该支持它。 Webkit 似乎没有实施时间表。


如果我们可以使用一个简单的内置函数,这会很棒,但它的浏览器实现很糟糕。例如,IE 8-10 和所有 Safari 都不支持这个
@BlaineKasten 这里有一个完全兼容的旧版浏览器的 polyfill:github.com/andyearnshaw/Intl.js 它很大,但它可以工作。
可通过 pollyfill CDN 获得(仅根据用户代理返回所需内容):cdn.polyfill.io/v2/polyfill.min.js?features=Intl
使用 toLocaleString 格式化大数字时出现问题,这很好用(使用 polyfill)
m
mariobgr

您可以使用此过程来格式化您需要的货币。

var nf = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’

有关更多信息,您可以访问此链接。

https://www.justinmccandless.com/post/formatting-currency-in-javascript/


这是正确的、可移植的、原生的答案。希望我能多次投票。
S
Shital Shah

如果您正在处理货币值并进行大量格式化,那么添加处理大量边缘情况和本地化的微小 accounting.js 可能是值得的:

// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00

// European formatting (custom symbol and separators), could also use options object as second param:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99

// Negative values are formatted nicely, too:
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

链接不再起作用。但看起来类似于这个:openexchangerates.github.io/accounting.js
I
Ice_mank
var number = 2561556862056.12;

console.log(new Intl.NumberFormat().format(number));

这是我发现的最简单的方法


仅供参考,这里似乎已经提到过:stackoverflow.com/a/32154217/28324
f
fregante

以下代码使用字符扫描,因此没有正则表达式。

function commafy( num){
  var parts = (''+(num<0?-num:num)).split("."), s=parts[0], L, i=L= s.length, o='';
  while(i--){ o = (i===0?'':((L-i)%3?'':',')) 
                  +s.charAt(i) +o }
  return (num<0?'-':'') + o + (parts[1] ? '.' + parts[1] : ''); 
}

它显示出有希望的性能:http://jsperf.com/number-formatting-with-commas/5

2015.4.26:小修复以解决 num<0 时的问题。请参阅https://jsfiddle.net/runsun/p5tqqvs3/


这不适用于 commafy(-123456) 它提供 -,123,456
这很棒!感谢您整理 jsperf
这个片段是一个绝对的怪物,执行一切。
a
aleclarson

这是一个为千位分隔符插入逗号的简单函数。它使用数组函数而不是 RegEx。

/**
 * Format a number as a string with commas separating the thousands.
 * @param num - The number to be formatted (e.g. 10000)
 * @return A string representing the formatted number (e.g. "10,000")
 */
var formatNumber = function(num) {
    var array = num.toString().split('');
    var index = -3;
    while (array.length + index > 0) {
        array.splice(index, 0, ',');
        // Decrement by 4 since we just added another unit to the array.
        index -= 4;
    }
    return array.join('');
};

带有示例的 CodeSandbox 链接:https://codesandbox.io/s/p38k63w0vq


嗨..这个例子很棒。但它也会为小数部分加上逗号。只是一个编辑: function formatNumber( num ) { var decimalPart = ''; num = num.toString(); if ( num.indexOf( '.' ) != -1 ) { decimalPart = '.'+ num.split( '.' )[1]; num = parseInt(num.split('.')[0]); } var 数组 = num.toString().split( '' );变量索引 = -3; while (array.length + index > 0) { array.splice(index, 0, ','); // 因为我们刚刚向数组中添加了另一个单元,所以递减 4。指数-= 4; } return array.join( '' ) + decimalPart; };
谢谢你,先生。这正是我所需要的。
B
Bathri Nathan

使用此代码处理印度的货币格式。可以更改国家代码以处理其他国家货币。

let amount =350256.95
var formatter = new Intl.NumberFormat('en-IN', {
  minimumFractionDigits: 2,
});

// Use it.

formatter.format(amount);

输出:

3,50,256.95

虽然此代码可能会回答问题,但提供有关其解决问题的方式和/或原因的附加上下文将提高答案的长期价值。Read this
@ShanteshwarInde 我会添加额外的上下文来改进答案
c
clozach

您还可以使用 Intl.NumberFormat 构造函数。这是你如何做到的。

 resultNumber = new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(yourNumber); 

这不工作的节点 js。它没有以印度格式给出回应
M
MMMahdy-PAPION

通用、快速、准确、功能简单

使用正则表达式(快速准确)

支持数字(浮点数/整数)/字符串/字符串中的多个数字

聪明的好(不分组小数 - 与不同类型的分组兼容)

支持所有浏览器,特别是“Safari”和“IE”以及许多旧版浏览器

[可选] 尊重非英语(波斯语/阿拉伯语)数字(+ 前缀)

TL;DR - 完整版功能(缩小版):

// num: Number/s (String/Number), // sep: 千位分隔符 (String) - 默认值: ',' // dec: 小数分隔符 (String) - 默认值: '.' (只有一个字符)// u:对语言字符的通用支持(字符串 - 正则表达式字符集/类) - 示例:'[\\d\\u0660-\\u0669\\u06f0-\\u06f9]'(英语/波斯语/阿拉伯语),默认值:'\\d'(英语)函数 formatNums(num,sep,dec,u){sep=sep||',';u=u||'\\d';if(typeof num!='string'){num=String(num);if(dec&&dec!='.')num=num.replace('.',dec);}return num.replace(RegExp('\\'+ (dec||'.')+u+'+|'+u+'(?=(?:'+u+'{3})+(?!'+u+'))','g'),function( a){return a.length == 1?a+sep:a})} text ='100000000英语或波斯/阿拉伯语۱۲۳۴۵۶۷۸۹/٠١٢٣٤٥٦٧٨٩,这是123123123.123123123,其中此-123123和这些10 100 1000 1000 123123/123/123123(200000000)。 33333 100.00 或任何类似 500000Kg'; console.log(formatNums(10000000.0012)); console.log(formatNums(10000000.0012,'.',',')); // 德语 console.log(formatNums(text,',','.','[\\d\\u0660-\\u0669\\u06f0-\\u06f9]')); // 尊重波斯/阿拉伯数字

为什么对其他答案不满意?

Number.prototype.toLocaleString() / Intl.NumberFormat (正确答案)如果没有很好的论据,我们不能期望相同的结果。同样使用参数选项,我们仍然无法确定结果是什么,因为它将使用本地设置和可能的客户端修改效果,或者浏览器/设备不支持它。 >~2016 年浏览器支持,并且仍在 2021 年,一些报告称在某些情况下,如 Safari 或 IE/Edge 不会按预期返回。 toLocaleString() 处理数字,Intl.NumberFormat 处理字符串/数字;字符串将/必须被解析并在必要时进行四舍五入,所以:如果我们已经有一个带有非英文数字的本地化字符串,我们必须用英文数字替换数字,然后解析它,然后再次使用本地选项. (如果它返回我们所期望的)通常在解析时我们不能期望不会丢失十进制零或大数字中的细节或尊重其他语言数字字符十进制/千位分隔符不能自定义超过语言选项,除了带有替换的后缀() + 正则表达式。 (例如在波斯语中,我们通常不使用建议的阿拉伯逗号,有时我们使用∕分数/除法斜线作为小数分隔符)循环中的性能缓慢

如果没有很好的论据,我们就不能期待同样的结果。同样使用参数选项,我们仍然无法确定结果是什么,因为它将使用本地设置和可能的客户端修改效果,或者浏览器/设备不支持它。

>~2016 年浏览器支持,并且仍在 2021 年,一些报告称在某些情况下,如 Safari 或 IE/Edge 不会按预期返回。

toLocaleString() 处理数字,Intl.NumberFormat 处理字符串/数字;字符串将/必须被解析并在必要时进行四舍五入,因此:如果我们已经有一个带有非英文数字的本地化字符串,我们必须用英文数字替换数字,然后解析它,然后再次使用本地选项. (如果它返回我们所期望的)通常在解析时我们不能期望不会丢失十进制零或大数字中的细节或尊重其他语言的数字字符

如果我们已经有一个非英文数字的本地化字符串,我们必须用英文数字替换数字,然后解析它,然后再次使用本地选项。 (如果它返回我们所期望的)

通常,在解析时,我们不能期望不会丢失十进制零或大数字中的细节或尊重其他语言的数字字符

十进制/千位分隔符不能自定义超过语言选项,除非再次使用 replace() + RegEx 进行后缀。 (例如在波斯语中,我们通常不使用建议的阿拉伯逗号,有时我们使用∕分数/除法斜杠作为小数分隔符)

循环性能缓慢

不太好的正则表达式方式(最快和单行方式) /\B(?=(\d{3})+\b)/ 它也会对小数进行分组。 // 123,123.123,123 !!! /(?

/\B(?=(\d{3})+\b)/ 它也会对小数进行分组。 // 123,123.123,123 !!!

/(?

/\B(?=(?=\d*\.)(\d{3})+(?!\d))/ 只使用浮点数并忽略整数。

.replace(/(?:[^.\d]|^)\d+/g,function(a){return a.replace(/\B(?=(?:\d{3})+\b) /g,',');}) (我的旧想法)使用 2 RegEx。第一个找到整数部分,第二个放置分隔符。为什么有 2 个功能,什么时候可以混合使用?

/(\..*)$|(\d)(?=(\d{3})+(?!\d))/g (@djulien 的好主意 - 我投了赞成票)但是当 RegEx 是全球性的, (\..*)$ 即使结尾有空格也可能出错。同样使用捕获组(示例:(\d))会降低性能,因此如果可能,请使用非捕获组(示例:(?:\d)),或者如果我们的函数中已经存在语句,让我们混合它。在这种情况下,不使用捕获组可以提高大约 20% 的性能,并且在 /\B(?=(\d{3})+\b)/g 与 /\B(?=(?:\d{ 3})+\b)/g,第二个要快 8%。关于正则表达式的性能: 注意:当然不同的方法、浏览器、硬件、系统状态、案例甚至 ECMAScript 上的更改都会影响检查性能的结果。但是从逻辑上讲,一些更改应该会影响结果,我将这个更改用作视觉示例。

使用像 Numeral.js 这样的库对于简单的任务来说并不是必需的功能。

使用 .split('.') 或 .toFixed() 或 Math.floor() 的繁重代码/不准确的函数 ...

最后结果:

没有最好的,应该根据需要来选择。我的排序优先级;

兼容性 能力 通用性 易用性 性能

toLocaleString() (兼容性 - 通用性) [本机函数]

如果您必须将数字和分组从英语更改为另一种语言

如果您不确定您的客户语言

如果您不需要确切的预期结果

如果您不关心旧版本的 Safari

// 1000000.2301
parseFloat(num) // (Pre-fix) If the input is string
    .toLocaleString('en-US', {
        useGrouping: true // (Default is true, here is just for show)
    });
// 1,000,000.23

阅读更多:https://www.w3schools.com/jsref/jsref_tolocalestring_number.asp

Intl.NumberFormat() (能力 - 通用性 - 兼容性) [原生函数]

toLocaleString() + 几乎相同

支持货币、单位等的强大能力...任何语言(现代浏览器)

// 1000000.2301
new Intl.NumberFormat('en-US', { // It can be 'fa-IR' : Farsi - Iran
    numberingSystem: 'arab'
}).format(num)
// ١٬٠٠٠٬٠٠٠٫٢٣

阅读更多:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat

有了这么多的原生函数选项,我们还是不能指望:

确切结果(+ 不解析输入/不四舍五入/不转换大数字)

接受其他语言数字作为输入

自定义分隔符

信任浏览器支持

表现

所以你可能需要一个像这样的函数:

formatNums()(兼容性 - 易用性)

完整版(能力)(不比 toLocaleString 快) - 解释:

function formatNums(num, sep, dec, u) {
    // Setting defaults
    sep = sep || ','; // Seperator
    u = u || '\\d'; // Universal character set \d: 0-9 (English)
    // Mixing of Handeling numbers when the decimal character should be changed + Being sure the input is string
    if (typeof num != 'string') {
        num = String(num);
        if (dec && dec != '.') num = num.replace('.', dec); // Replacing sure decimal character with the custom
    }
    //
    return num.replace(RegExp('\\' + (dec || '.') + u + '+|' + u + '(?=(?:' + u + '{3})+(?!' + u + '))', 'g'),
        // The RegEx will be like /\.\d+|\d(?=(?:\d{3})+(?!\d))/g if not be customized 
        // RegEx explain:
        // 1) \.\d+  :  First try to get any part that started with a dot and followed by any much of English digits, one or more (For ignoring it later)
        // 2) |  :  Or
        // 3) \d  :  Get any 1 char digit
        // 3.1) (?=...)  :  That the next of that should be
        // 3.2) (?:\d{3})  :  3 length digits
        // 3.2.1) +  :  One or more of the group
        // 3.3) (?!\d)  :  ...till any place that there is no digits
        function(a) { // Any match can be the decimal part or the integer part so lets check it
            return a.length == 1 ? a + sep : a // If the match is one character, it is from the grouping part as item (3) in Regex explain so add the seperator next of it, if not, ignore it and return it back.
        })
}

函数 formatNums(num,sep,dec,u) { sep=sep||','; u=u||'\\d'; if(typeof num!='string') { num=String(num); if(dec && dec!='.') num=num.replace('.',dec); } return num.replace(RegExp('\\'+(dec||'.')+u+'+|'+u+'(?=(?:'+u+'{3})+(?!'+ u+'))','g'),function(a) {return a.length==1 ? a+sep : a}) } console.log(formatNums(1000000.2301)); console.log(formatNums(100.2301)); console.log(formatNums(-2000.2301)); console.log(formatNums(123123123,' , ')); console.log(formatNums('0000.0000')); console.log(formatNums('5000000.00')); console.log(formatNums('5000000,00','',',')); console.log(formatNums(5000000.1234,'',',')); console.log(formatNums('12364556778۹/۹000',',','/','[\\d\\u0660-\\u0669\\u06f0-\\u06f9]'));

试玩此处的示例:https://jsfiddle.net/PAPIONbit/198xL3te/

轻量版(性能)(比 toLocaleString 快约 30%)

函数 formatNums(num,sep) { sep=sep||','; return String(num).replace(/\.\d+|\d(?=(?:\d{3})+(?!\d))/g, function(a) { return a.length== 1?a+sep:a } ); } console.log(formatNums(1000000.2301)); console.log(formatNums(100.2301)); console.log(formatNums(-2000.2301)); console.log(formatNums(123123123,' '));

检查正则表达式(没有必要的功能):https://regexr.com/66ott

(num+'').replace(/\B(?=(?:\d{3})+\b)/g,','); (性能 - 兼容性)

最好选择输入是否指定/预定义。 (与通常的价格一样,小数点后不超过 3 位)(比 toLocaleString 快约 65%)

数=1000000; str='123123.100'; console.log((num+'').replace(/\B(?=(?:\d{3})+\b)/g,',')); console.log(str.replace(/\B(?=(?:\d{3})+\b)/g,','));

+

对于波斯语/阿拉伯语本地客户:

如果您的客户要像在伊朗一样使用波斯/阿拉伯数字进行输入,我认为最好的方法是不要保留原始字符,而是在处理之前将它们转换为英文,以便您计算它。

// ۱۲۳۴۵۶۷۸۹۰
function toEnNum(n) { // Replacing Persian/Arabic numbers character with English
    n.replace(/[\u0660-\u0669\u06f0-\u06f9]/g, // RegEx unicode range Persian/Arabic numbers char
        function(c) {
            return c.charCodeAt(0) & 0xf; // Replace the char with real number by getting the binary index and breaking to lowest using 15
        }
    );
}
// 1234567890

为了仍然将它们显示为原始外观,有两种方法:

CSS 使用带有本地数字的波斯/阿拉伯字体(我的选择)

使用 Intl.NumberFormat 或类似的函数将结果转换回:https://stackoverflow.com/a/13787021/7514010

我在这篇文章中的老派功能:(比 toLocalString 快~15%)

// 10000000.0012
function formatNums(n, s) {
    return s = s || ",", String(n).
    replace(/(?:^|[^.\d])\d+/g, // First this RegEx take just integer parts
        function(n) {
            return n.replace(/\B(?=(?:\d{3})+\b)/g, s);
        })
}
// 10,000,000.0012

这不是代码高尔夫。我认为使用一些空格和换行符来使您的代码更具可读性是可以的,即使它们不是严格要求的。
@elias-zamaria 现在通过新功能检查一下,我删除了负面的外观,因为并非所有浏览器都支持
K
Kiry Meas
var formatNumber = function (number) {
  var splitNum;
  number = Math.abs(number);
  number = number.toFixed(2);
  splitNum = number.split('.');
  splitNum[0] = splitNum[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return splitNum.join(".");
}

编辑:该功能仅适用于正数。例如:

var number = -123123231232;
formatNumber(number)

输出:“123,123,231,232”

但是回答上面的问题toLocaleString()方法只是解决了问题。

var number = 123123231232;
    number.toLocaleString()

输出:“123,123,231,232”

欢呼!


虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。
不错的脚本,但它不适用于负数。
L
Lonnie Best

我的答案是用更明智的选择完全取代 jQuery 的唯一答案:

function $(dollarAmount)
{
    const locale = 'en-US';
    const options = { style: 'currency', currency: 'USD' };
    return Intl.NumberFormat(locale, options).format(dollarAmount);
}

该解决方案不仅添加了逗号,而且如果您输入像 $(1000.9999) 这样的金额,它还会四舍五入到最接近的美分,您将获得 1,001.00 美元。此外,您输入的值可以安全地是数字或字符串;没关系。

如果您正在处理金钱,但不想在金额上显示前导美元符号,您还可以添加此函数,该函数使用之前的函数但删除了 $

function no$(dollarAmount)
{
    return $(dollarAmount).replace('$','');
}

如果您不处理金钱,并且有不同的十进制格式要求,这里有一个更通用的功能:

function addCommas(number, minDecimalPlaces = 0, maxDecimalPlaces = Math.max(3,minDecimalPlaces))
{
    const options = {};
    options.maximumFractionDigits = maxDecimalPlaces;
    options.minimumFractionDigits = minDecimalPlaces;
    return Intl.NumberFormat('en-US',options).format(number);
}

哦,顺便说一句,这段代码在某些旧版本的 Internet Explorer 中不起作用的事实完全是故意的。我会在任何时候尝试破解 IE,只要我发现它不支持现代标准。

请记住,在评论部分过度赞美被认为是题外话。相反,只需向我投赞成票即可。


Number(n).toLocaleString() 似乎是最好的答案,但如果所有用户想要的是他们号码中的逗号。
@bmacnaughton:当您不与金钱打交道时,这是一个很好的观点。但是,如果您正在处理金钱,并且只是“不想要领先的美元符号”,Number(1000.50).toLocaleString() 会产生 '1,000.5',它会删除通常在显示金钱值时保留的微不足道的零。不过评论很好:每个人都应该知道你说了什么。
R
Ronnie Overby

我在偶然发现这篇文章之前写了这篇文章。没有正则表达式,您实际上可以理解代码。

$(function(){ function insertCommas(s) { // 获取点之前的内容 var d = s.indexOf('.'); var s2 = d === -1 ? s : s.slice(0, d ); // 从右边开始每隔 3 位插入逗号 for (var i = s2.length - 3; i > 0; i -= 3) s2 = s2.slice(0, i) + ',' + s2.slice (i); // 添加小数部分 if (d !== -1) s2 += s.slice(d); return s2; } $('#theDudeAbides').text( insertCommas('1234567.89012' ) ); });


我在函数开头添加了 s.toString() ,因此它也可以接受数字,而不仅仅是字符串。这是我的首选答案,因为它可读、简洁,并且没有正则表达式答案似乎有的错误。
仅当您传递一个字符串时才有效.. 一个简单的修复,但只是想注意它
d
djulien

对于喜欢 1-liners 和单个正则表达式但不想使用 split() 的任何人,这里是处理(忽略)小数位的其他答案的正则表达式的增强版本:

    var formatted = (x+'').replace(/(\..*)$|(\d)(?=(\d{3})+(?!\d))/g, (digit, fract) => fract || digit + ',');

正则表达式首先匹配以文字“。”开头的子字符串。并将其替换为自身(“fract”),然后匹配任何数字,后跟 3 位的倍数,并在其后加上“,”。

例如,x = 12345678.12345678 将给出 formatted = '12,345,678.12345678'。


C
Community

让我尝试改进 uKolkaanswer,也许可以帮助其他人节省一些时间。

使用 Numeral.js

document.body.textContent = numeric(1234567).format('0,0');

只有当它的 browser compatibilty 不是问题时,您才应该使用 Number.prototype.toLocaleString()


这启发了我 npm install numeric
I
Igor Bykov

仅针对未来的 Google 员工(或不一定是“Google 员工”):

上面提到的所有解决方案都很棒,但是,在这种情况下使用 RegExp 可能是非常糟糕的事情。

所以,是的,您可能会使用一些建议的选项,甚至编写一些原始但有用的东西,例如:

const strToNum = str => {

   //Find 1-3 digits followed by exactly 3 digits & a comma or end of string
   let regx = /(\d{1,3})(\d{3}(?:,|$))/;
   let currStr;

   do {
       currStr = (currStr || str.split(`.`)[0])
           .replace( regx, `$1,$2`)
   } while (currStr.match(regx)) //Stop when there's no match & null's returned

   return ( str.split(`.`)[1] ) ?
           currStr.concat(`.`, str.split(`.`)[1]) :
           currStr;

};

strToNum(`123`) // => 123
strToNum(`123456`) // => 123,456
strToNum(`-1234567.0987`) // => -1,234,567.0987

此处使用的正则表达式相当简单,循环将精确地执行完成工作所需的次数。

你可能会更好地优化它,“DRYify”代码等等。

然而,

(-1234567.0987).toLocaleString();

(在大多数情况下)将是一个更好的选择。

关键不在于执行速度或跨浏览器兼容性。

在您想向用户显示结果数字的情况下,.toLocaleString() 方法使您能够与您的网站或应用程序的用户使用相同的语言(无论她/他的语言是什么)。

这种根据 ECMAScript 文档的方法是在 1999 年引入的,我相信这样做的原因是希望互联网在某个时候能够连接世界各地的人们,因此需要一些“内化”工具。

今天,互联网确实连接了我们所有人,因此,重要的是要记住,世界比我们想象的要复杂得多,而且(/几乎)我们所有人都在这里,在互联网上。

显然,考虑到人的多样性,不可能保证每个人都能获得完美的用户体验,因为我们说不同的语言,重视不同的事物等等。正因为如此,尽可能多地尝试本地化变得更加重要.

所以,考虑到日期、时间、数字等的表示有一些特定的标准,并且我们有一个工具可以以最终用户喜欢的格式显示这些东西,这并不罕见,而且几乎是不负责任的使用该工具(尤其是在我们想向用户显示此数据的情况下)?

对我来说,在这种情况下使用 RegExp 而不是 .toLocaleString() 听起来有点像用 JavaScript 创建时钟应用程序并以这种方式对其进行硬编码,因此它只会显示布拉格时间(这对于不住在布拉格的人)即使默认行为

new Date();

是根据最终用户的时钟返回数据。


你为什么用 const 和 => 编写函数?
@OGSean 我总是这样做,因为它是声明变量和函数的最方便的方式。另外,我认为它有助于保持代码更简洁和更短。
这是正确的答案,人们过于复杂了。 toLocaleString() 就是为这个确切的用例而构建的。
m
mjs

另一种方式,支持小数、不同的分隔符和负数。

var number_format = function(number, decimal_pos, decimal_sep, thousand_sep) {
    var ts      = ( thousand_sep == null ? ',' : thousand_sep )
        , ds    = ( decimal_sep  == null ? '.' : decimal_sep )
        , dp    = ( decimal_pos  == null ? 2   : decimal_pos )

        , n     = Math.floor(Math.abs(number)).toString()

        , i     = n.length % 3 
        , f     = ((number < 0) ? '-' : '') + n.substr(0, i)
    ;

    for(;i<n.length;i+=3) {
        if(i!=0) f+=ts;
        f+=n.substr(i,3);
    }

    if(dp > 0) 
        f += ds + parseFloat(number).toFixed(dp).split('.')[1]

    return f;
}

@Jignesh Sanghani 的一些更正,不要忘记支持他的评论。


非常适合我,只是添加了一个新行以在处理之前删除格式。
fn.substr(0, i) 替换为 n.substr(0, i) 并且 number.toFixed(dp).split('.')[1] 替换为 parseFloat(number).toFixed(dp).split('.')[1]。因为当我直接使用时,它会给我带来错误。请更新您的代码
有缺陷。数量增长。一个示例电话会很棒!
将 ceil 切换到 floor 解决了这个问题,但不确定还会出现什么其他问题。
试试 Math.floor(-75.1) ;)
R
ROMANIA_engineer

我认为此功能将处理与此问题相关的所有问题。

function commaFormat(inputString) {
    inputString = inputString.toString();
    var decimalPart = "";
    if (inputString.indexOf('.') != -1) {
        //alert("decimal number");
        inputString = inputString.split(".");
        decimalPart = "." + inputString[1];
        inputString = inputString[0];
        //alert(inputString);
        //alert(decimalPart);

    }
    var outputString = "";
    var count = 0;
    for (var i = inputString.length - 1; i >= 0 && inputString.charAt(i) != '-'; i--) {
        //alert("inside for" + inputString.charAt(i) + "and count=" + count + " and outputString=" + outputString);
        if (count == 3) {
            outputString += ",";
            count = 0;
        }
        outputString += inputString.charAt(i);
        count++;
    }
    if (inputString.charAt(0) == '-') {
        outputString += "-";
    }
    //alert(outputString);
    //alert(outputString.split("").reverse().join(""));
    return outputString.split("").reverse().join("") + decimalPart;
}

R
Robo Robok

如果您正在寻找一个简短而甜蜜的解决方案:

const number = 12345678.99;

const numberString = String(number).replace(
    /^\d+/,
    number => [...number].map(
        (digit, index, digits) => (
            !index || (digits.length - index) % 3 ? '' : ','
        ) + digit
    ).join('')
);

// numberString: 12,345,678.99

那是告诉我“未捕获的 TypeError:数字不可迭代”。也许您需要拨打该号码的 toString
@EliasZamaria 对不起,我在我的案例中使用了一个字符串。更新了我的答案以转换为字符串。
我尝试将 12.34 作为数字并返回 12,.34
我认为它只适用于小数。为你更新。