如何格式化一个用逗号作为千分隔符的数字?

我正在尝试用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;}

有更简单或更优雅的方法吗?如果它也适用于浮点数,那就太好了,但这不是必要的。它不需要特定于语言环境来决定句点和逗号。

1910328 次浏览

我建议使用phpjs.orgnumber_format()

function number_format(number, decimals, dec_point, thousands_sep) {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);}

更新02/13/14

人们一直在报告这并没有像预期的那样工作,所以我做了一个包含自动化测试的jsfiddle

更新26/11/2017

这是一个稍微修改输出的Stack Snippet小提琴:

function number_format(number, decimals, dec_point, thousands_sep) {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);}
var exampleNumber = 1;function test(expected, number, decimals, dec_point, thousands_sep){var actual = number_format(number, decimals, dec_point, thousands_sep);console.log('Test case ' + exampleNumber + ': ' +'(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) +', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' +', thousands_sep: "' + (typeof thousands_sep === 'undefined' ? '(default)' : thousands_sep) + '")');console.log('  => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", expected "' + expected + '".');exampleNumber++;}
test('1,235',    1234.56);test('1 234,56', 1234.56, 2, ',', ' ');test('1234.57',  1234.5678, 2, '.', '');test('67,00',    67, 2, ',', '.');test('1,000',    1000);test('67.31',    67.311, 2);test('1,000.6',  1000.55, 1);test('67.000,00000', 67000, 5, ',', '.');test('1',        0.9, 0);test('1.20',     '1.20', 2);test('1.2000',   '1.20', 4);test('1.200',    '1.2000', 3);
.as-console-wrapper {max-height: 100% !important;}

我认为你的解决方案是我见过的较短的解决方案之一。我不认为有任何标准的JavaScript函数可以做这种事情,所以你可能需要自己。

我检查了CSS 3规范,看看是否可以在CSS中做到这一点,但除非您希望每个数字都有自己的<span>,否则我认为这是不可能的。

我确实在google代码上找到了一个看起来很有希望的项目:灵活的js格式。我还没有使用过它,但它看起来很灵活,并且使用JsUnit进行了单元测试。开发人员也有很多关于这个主题的帖子(虽然很旧)。

一定要考虑国际用户:许多国家使用空格作为分隔符,并使用逗号将小数与数字的组成部分分开。

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

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

function numberWithCommas(x) {return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");}
function test(x, expect) {const result = numberWithCommas(x);const pass = result === expect;console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`);return pass;}
let failures = 0;failures += !test(0,        "0");failures += !test(100,      "100");failures += !test(1000,     "1,000");failures += !test(10000,    "10,000");failures += !test(100000,   "100,000");failures += !test(1000000,  "1,000,000");failures += !test(10000000, "10,000,000");if (failures) {console.log(`${failures} test(s) failed`);} else {console.log("All tests passed");}
.as-console-wrapper {max-height: 100% !important;}


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

  • 一个正数,用于查找字符串中的任何点,该点后面有3位数字的倍数,
  • 一个否定断言,以确保该点只有3位数字的倍数。替换表达式在那里放了一个逗号。

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

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

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

function numberWithCommas(x) {var parts = x.toString().split(".");parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");return parts.join(".");}
function test(x, expect) {const result = numberWithCommas(x);const pass = result === expect;console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`);return pass;}
let failures = 0;failures += !test(0              , "0");failures += !test(0.123456       , "0.123456");failures += !test(100            , "100");failures += !test(100.123456     , "100.123456");failures += !test(1000           , "1,000");failures += !test(1000.123456    , "1,000.123456");failures += !test(10000          , "10,000");failures += !test(10000.123456   , "10,000.123456");failures += !test(100000         , "100,000");failures += !test(100000.123456  , "100,000.123456");failures += !test(1000000        , "1,000,000");failures += !test(1000000.123456 , "1,000,000.123456");failures += !test(10000000       , "10,000,000");failures += !test(10000000.123456, "10,000,000.123456");if (failures) {console.log(`${failures} test(s) failed`);} else {console.log("All tests passed");}
.as-console-wrapper {max-height: 100% !important;}

@t.j.crowder指出,现在JavaScript已经有了look(支持信息),它可以在正则表达式本身中解决:

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

function numberWithCommas(x) {return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");}
function test(x, expect) {const result = numberWithCommas(x);const pass = result === expect;console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`);return pass;}
let failures = 0;failures += !test(0,               "0");failures += !test(0.123456,        "0.123456");failures += !test(100,             "100");failures += !test(100.123456,      "100.123456");failures += !test(1000,            "1,000");failures += !test(1000.123456,     "1,000.123456");failures += !test(10000,           "10,000");failures += !test(10000.123456,    "10,000.123456");failures += !test(100000,          "100,000");failures += !test(100000.123456,   "100,000.123456");failures += !test(1000000,         "1,000,000");failures += !test(1000000.123456,  "1,000,000.123456");failures += !test(10000000,        "10,000,000");failures += !test(10000000.123456, "10,000,000.123456");if (failures) {console.log(`${failures} test(s) failed`);} else {console.log("All tests passed");}
.as-console-wrapper {max-height: 100% !important;}

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

这是一个为一千个分隔符插入逗号的简单函数。它使用数组函数而不是正则表达式。

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

这是@mikez302答案的变体,但修改为支持带有小数的数字(根据@neu-rah的反馈,numberWith Commas(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] : "");}

感谢大家的回复,我总结了其中的一些答案,做出了更“一刀切”的解法。

第一个代码段将一个模仿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.00console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

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

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.00var fooFloat = fooString.getFloat(); // The number 5000;
console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00

我添加到固定Aki143S的解决方案。此解决方案使用点表示数千个分隔符,逗号表示精度。

function formatNumber( num, fixed ) {var decimalPart;
var array = Math.floor(num).toString().split('');var index = -3;while ( array.length + index > 0 ) {array.splice( index, 0, '.' );index -= 4;}
if(fixed > 0){decimalPart = num.toFixed(fixed).split(".")[1];return array.join('') + "," + decimalPart;}return array.join('');};

实例;

formatNumber(17347, 0)  = 17.347formatNumber(17347, 3)  = 17.347,000formatNumber(1234563.4545, 3)  = 1.234.563,454

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

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

来自@user1437663的解决方案很棒。

真正理解解决方案的人正在准备理解复杂的正则表达式。

一个小改进,使其更具可读性:

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

模式以\B开头,以避免在单词开头使用逗号。有趣的是,模式返回为空,因为\B没有推进“光标”(同样适用于$)。

O\B后面跟着一个鲜为人知的资源,但它是Perl正则表达式的一个强大功能。

            Pattern1 (? = (Pattern2) ).

神奇的是,括号(模式2)中的内容是一个遵循前一个模式(模式1)但没有推进光标的模式,也不是返回模式的一部分。这是一种未来模式。当有人向前看但真的不走路时,这是类似的!

在这种情况下模式2

\d{3})+(?=$)

它意味着3位数字(一次或多次)后跟字符串末尾($)

最后,替换方法将所有出现的模式(空字符串)更改为逗号。这仅发生在剩余部分是3位数倍数的情况下(未来光标到达原点末尾的情况)。

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

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

通过包含Intl,它也可以在v0.12的Node.js中工作

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

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

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/

另一个…(对于问题所问的int)

function insertCommas(str){var a = str.split("");a.reverse();
var t, i = 0, arr = Array();
while (t = a.shift()){if (((i++ % 3) == 0) && arr.length > 0)arr.unshift(",");arr.unshift(t);}
return arr.join("");}

已经有很多很好的答案了。这是另一个,只是为了好玩:

function format(num, fix) {var p = num.toFixed(fix).split(".");return p[0].split("").reduceRight(function(acc, num, i, orig) {if ("-" === num && 0 === i) {return num + acc;}var pos = orig.length - i - 1return  num + (pos && !(pos % 3) ? "," : "") + acc;}, "") + (p[1] ? "." + p[1] : "");}

一些例子:

format(77.03453, 2); // "77.03"format(78436589374); // "78,436,589,374"format(784, 4);      // "784.0000"format(-123456);     // "-123,456"

如果你正在处理货币值和格式化很多,那么可能值得添加微小的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

这是一个很好的解决方案,编码较少…

var y = "";var arr = x.toString().split("");for(var i=0; i<arr.length; i++){y += arr[i];if((arr.length-i-1)%3==0 && i<arr.length-1) y += ",";}

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

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

有关更多信息,请参阅MDN关于NumberFormat的文章,您可以指定区域设置行为或默认为用户的行为。这更万无一失,因为它尊重局部差异;许多国家使用句点分隔数字,而逗号表示小数。

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

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

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的一些更正,不要忘记支持他的评论。

function formatNumber (num) {return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")}
print(formatNumber(2665));      // 2,665print(formatNumber(102665));    // 102,665print(formatNumber(111102665)); // 111,102,665

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

$(function(){  
function insertCommas(s) {
// get stuff before the dotvar d = s.indexOf('.');var s2 = d === -1 ? s : s.slice(0, d);
// insert commas every 3 digits from the rightfor (var i = s2.length - 3; i > 0; i -= 3)s2 = s2.slice(0, i) + ',' + s2.slice(i);
// append fractional partif (d !== -1)s2 += s.slice(d);
return s2;
}  
  
$('#theDudeAbides').text( insertCommas('1234567.89012' ) );  
  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="theDudeAbides"></div>

让我试着改进uKolka回答,也许可以帮助其他人节省一些时间。

使用Numeral.js

document.body.textContent = numeral(1234567).format('0,0');
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>

只有当它的浏览器兼容性不是问题时,你才应该使用Number.prototype.toLocaleString()

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

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

我检查了几个数字,它奏效了。

我已经调整了您的代码以在TextBox(输入类型="text")中工作,因此我们可以实时输入和删除数字而不会丢失光标。如果您在删除时选择范围,它也可以工作。您可以自由使用箭头和home/end按钮。
谢谢你帮我节省时间!

//function controls number format as "1,532,162.3264321"function numberWithCommas(x) {var e = e || window.event;if (e.keyCode >= '35' && e.keyCode <= '40') return; //skip arrow-keysvar selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positionsvar parts = x.value.toString().split(".");var part0len = parts[0].length; //old length to check if new ',' would be added. Need for correcting new cursor position (+1 to right).
//if user deleted ',' - remove previous number instead (without selection)if (x.selectionLength == 0 && (e.keyCode == 8 || e.keyCode == 46)) {//if pressed 8-backspace or 46-delete buttonvar delPos = parts[0].search(/\d{4}/);if (delPos != -1) {//if found 4 digits in a row (',' is deleted)if (e.keyCode == 8) {//if backspace flagparts[0] = parts[0].slice(0, selStart - 1) + parts[0].slice(selEnd, parts[0].length);selEnd--;if (selStart > selEnd) selStart = selEnd;} else {parts[0] = parts[0].slice(0, selStart) + parts[0].slice(selEnd + 1, parts[0].length);selStart++;if (selEnd < selStart) selEnd = selStart;}}}
var hasMinus = parts[0][0] == '-';parts[0] = (hasMinus ? '-' : '') + parts[0].replace(/[^\d]*/g, ""); //I'd like to clear old ',' to avoid things like 1,2,3,5,634.443216parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digitsif (part0len < parts[0].length) { //move cursor to right if added new ','selStart++;selEnd++;} else if (part0len > parts[0].length) { //..or if removed last one ','selStart--;selEnd--;}x.value = parts.join(".");x.setSelectionRange(selStart, selEnd); //restoring cursor position}function saveSelectionLength(x) {x.selectionLength = x.selectionEnd - x.selectionStart;}

要使用它,只需添加两个事件-onKeyUp和onKeyDown

<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>

以下是可以将数字转换为结构化弦乐的两种不同的浏览器API。请记住,并非所有用户的机器都有locale在数字中使用逗号。为了在输出中强制使用逗号,可以使用任何“西方”区域设置,例如en-US

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

⚠️注意JavaScript的最大整数值为9007199254740991


toLocaleString

// default behaviour on a machine with a local that uses commas for numberslet number = 1234567890;number.toLocaleString(); // "1,234,567,890"
// With custom settings, forcing a "US" locale to guarantee commas in outputlet number2 = 1234.56789; // floating point examplenumber2.toLocaleString('en-US', {maximumFractionDigits:2}); // "1,234.57"
//You can also force a minimum of 2 trailing digitslet number3 = 1.5;number3.toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2}); //"1.50"

NumberFormat

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

我想分享一个用于大数格式的小技巧。我没有插入逗号或空格,而是在“千”之间插入一个空但可见的跨度。这使得数千很容易看到,但它允许以原始格式复制/粘贴输入,没有逗号/空格。

// This function accepts an integer, and produces a piece of HTML that shows it nicely with// some empty space at "thousand" markers.// Note, these space are not spaces, if you copy paste, they will not be visible.function valPrettyPrint(orgVal) {// Save after-comma text, if presentvar period = orgVal.indexOf(".");var frac = period >= 0 ? orgVal.substr(period) : "";// Work on input as an integervar val = "" + Math.trunc(orgVal);var res = "";while (val.length > 0) {res = val.substr(Math.max(0, val.length - 3), 3) + res;val = val.substr(0, val.length - 3);if (val.length > 0) {res = "<span class='thousandsSeparator'></span>" + res;}}// Add the saved after-period informationres += frac;return res;}

使用此CSS:

.thousandsSeparator {display : inline;padding-left : 4px;}

看一个例子JSFiddle。

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

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

var putThousandsSeparators;
putThousandsSeparators = function(value, sep) {if (sep == null) {sep = ',';}// check if it needs formattingif (value.toString() === value.toLocaleString()) {// split decimalsvar parts = value.toString().split('.')// format whole numbersparts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);// put them back togethervalue = parts[1] ? parts.join('.') : parts[0];} else {value = value.toLocaleString();}return value;};
alert(putThousandsSeparators(1234567.890));

如果您碰巧使用AngularJS,那么这个货币过滤器肯定会有所帮助:http://www.w3schools.com/angular/ng_filter_currency.asp

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"

干杯!

这是我的尝试:

编辑:以小数添加

function splitMille(n, separator = ',') {// Cast to stringlet num = (n + '')
// Test for and get any decimals (the later operations won't support them)let decimals = ''if (/\./.test(num)) {// This regex grabs the decimal point as well as the decimal numbersdecimals = num.replace(/^.*(\..*)$/, '$1')}  
// Remove decimals from the number stringnum = num.replace(decimals, '')// Reverse the number string through Array functions.split('').reverse().join('')// Split into groups of 1-3 characters (with optional supported character "-" for negative numbers).match(/[0-9]{1,3}-?/g)// Add in the mille separator character and reverse back.join(separator).split('').reverse().join('')
// Put the decimals back and output the formatted numberreturn `${num}${decimals}`}
let testA = splitMille(1234)let testB = splitMille(-1234)let testC = splitMille(123456.789)let testD = splitMille(9007199254740991)let testE = splitMille(1000.0001)
console.log('Results!\n\tA: %s\n\tB: %s\n\tC: %s\n\tD: %s\n\tE: %s', testA, testB, testC, testD, testE)

这是一个支持int和decimal的单行函数。我留下了一些代码来将数字转换为字符串。

    function numberWithCommas(x) {return (x=x+'').replace(new RegExp('\\B(?=(\\d{3})+'+(~x.indexOf('.')?'\\.':'$')+')','g'),',');}

int. NumberFormat

原生JS功能。支持IE11、Edge、最新Safari、Chrome、Firefox、Opera、iOSSafari和AndroidChrome。

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

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

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/

在这里没有找到一个现代和全面的解决方案之后,我写了一个箭头函数(没有正则表达式)来解决格式问题,它允许调用者提供小数位数的数字以及欧洲和世界其他地方的周期和千分隔符

示例:

numberFormatter(1234567890.123456) => 1,234,567,890numberFormatter(1234567890.123456, 4) => 1,234,567,890.1235numberFormatter(1234567890.123456, 4, '.', ',') => 1.234.567.890,1235 Europe

这是用ES6(现代语法)编写的函数:

const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => {if (number!==0 && !number || !Number.isFinite(number)) return numberconst frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0const num = number.toFixed(frDigits).toString()
const parts = num.split('.')let digits = parts[0].split('').reverse()let sign = ''if (num < 0) {sign = digits.pop()}let final = []let pos = 0
while (digits.length > 1) {final.push(digits.shift())pos++if (pos % 3 === 0) {final.push(thousandSeperator)}}final.push(digits.shift())return `${sign}${final.reverse().join('')}${frDigits > 0 ? fractionSeperator : ''}${frDigits > 0 && parts[1] ? parts[1] : ''}`}

它已经是测试负,坏输入和NaN情况。如果输入是NaN,那么它只是返回它。

我找到了一种在任何情况下都有效的方法。

function commas(n) {if (n < 1000) {return n + ''} else {// Convert to string.n += ''
// Skip scientific notation.if (n.indexOf('e') !== -1) {return n}
// Support fractions.let i = n.indexOf('.')let f = i == -1 ? '' : n.slice(i)if (f) n = n.slice(0, i)
// Add commas.i = n.lengthn = n.split('')while (i > 3) n.splice((i -= 3), 0, ',')return n.join('') + f}}

这类似于诺亚·弗雷塔斯的回答,但支持分数科学记数法

我认为toLocaleString是最好的选择,如果性能不是一个问题。

编辑:这是一个带有一些示例的CodeSandbox:https://codesandbox.io/s/zmvxjpj6x

使用正则表达式

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,890console.log(toCommas(1234)); // 1,234

使用toLocaleString()

var number = 123456.789;
// request a currency formatconsole.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));// → 123.456,79 €
// the Japanese yen doesn't use a minor unitconsole.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))// → ¥123,457
// limit to three significant digitsconsole.log(number.toLocaleString('en-IN', { maximumSignificantDigits: 3 }));// → 1,23,000

参考MDN:Number.prototype.toLocaleString()

使用int. 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 unitconsole.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));// expected output: "¥123,457"
// limit to three significant digitsconsole.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));
// expected output: "1,23,000"

参考数字格式

演示在这里

<script type="text/javascript">// Using Regular expressionfunction toCommas(value) {return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");}
function commas() {var num1 = document.myform.number1.value;
// Using Regular expressiondocument.getElementById('result1').value = toCommas(parseInt(num1));// Using toLocaleString()
document.getElementById('result2').value = parseInt(num1).toLocaleString('ja-JP', {style: 'currency',currency: 'JPY'});
// Using Intl.NumberFormat()document.getElementById('result3').value = new Intl.NumberFormat('ja-JP', {style: 'currency',currency: 'JPY'}).format(num1);}</script><FORM NAME="myform"><INPUT TYPE="text" NAME="number1" VALUE="123456789"><br><INPUT TYPE="button" NAME="button" Value="=>" onClick="commas()"><br>Using Regular expression<br><INPUT TYPE="text" ID="result1" NAME="result1" VALUE=""><br>Using toLocaleString()<br><INPUT TYPE="text" ID="result2" NAME="result2" VALUE=""><br>Using Intl.NumberFormat()<br><INPUT TYPE="text" ID="result3" NAME="result3" VALUE="">
</FORM>

性能

性能http://jsben.ch/sifRd

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

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

输出:

3,50,256.95

仅适用于未来的Google员工(或不一定是“Google员工”):

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

所以,是的,你可以使用一些建议的选项,甚至写一些原始但有用的东西,比如:

const strToNum = str => {
//Find 1-3 digits followed by exactly 3 digits & a comma or end of stringlet 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`) // => 123strToNum(`123456`) // => 123,456strToNum(`-1234567.0987`) // => -1,234,567.0987

这里使用的regexp相当简单,循环将精确地完成完成工作所需的次数。

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

然而,

(-1234567.0987).toLocaleString();

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

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

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

这种根据ECMAScript留档的方法是在1999年引入的,我相信其原因是希望互联网在某个时候将世界各地的人们联系起来,因此需要一些“内化”工具。

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

显然,考虑到人的多样性,不可能保证每个人都有完美的用户体验,因为我们说不同的语言,重视不同的东西等,正因为如此,尽可能本地化东西就更重要了。

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

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

new Date();

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

我的"true"纯正则表达式解决方案给那些爱的人

你看到上面那些热情的球员了吗?也许你可以打高尔夫球。这是我的击球。

n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " ").replace(/(?<=\.(\d{3})+)\B/g, " ")

使用#0薄空间(U+2009)表示千位分隔符,正如国际单位制第八版(2006)他们的出版物SI手册:国际单位制(SI)中所说的那样(参见§5.3.4.)。第九版(2019)建议使用空间(参见§5.4.4.)。您可以使用任何您想要的,包括逗号。


看。

const integer_part_only = n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ");const fractional_part_only = n => `${n}`.replace(/(?<=\.(\d{3})+)\B/g, " F ");const both = n => fractional_part_only(integer_part_only(n));
function demo(number) { // I’m using Chrome 74.console.log(`${number}→ "${integer_part_only(number)}" (integer part only)→ "${fractional_part_only(number)}" (fractional part only)→ "${both(number)}" (both)`);}demo(Math.random() * 10e5);demo(123456789.01234567);demo(123456789);demo(0.0123456789);


它是如何工作的?

对于整数部分

.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ")
  • .replace(……, " I ")放"I"
    • /……/g在每个
      • \B两个相邻数字的中间
        • (?=……)积极的展望谁的右边是
          • (\d{3})+一个或多个三位数块
          • \b后跟一个非数字,例如句点、字符串的结尾等,
        • (?<!……)消极的眼神不包括左边部分
          • \.\d+是一个点后跟数字(“具有十进制分隔符”)。

对于一个小数部分

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ")放"F"
    • /……/g在每个
      • \B两个相邻数字的中间
        • (?<=……)积极的目光的左边是
          • \.小数分隔符
          • (\d{3})+后跟一个或多个三位数块。

字符类边界

\d

匹配任何数字(阿拉伯数字)。等效于[0-9]

例如,

  • /\d//[0-9]/匹配B2 is the suite number中的2

\b

匹配字边界。这是一个单词字符后面或前面没有另一个单词字符的位置,例如在字母和空格之间。请注意,匹配中不包括匹配的单词边界。换句话说,匹配的单词边界的长度为零。

示例:

  • /\bm/匹配moon中的m
  • /oo\b/moon中的oo不匹配,因为oo后面跟着n,这是一个单词字符;
  • /oon\b/匹配moon中的oon,因为oon是字符串的结尾,因此后面没有单词字符;
  • /\w\b\w/永远不会匹配任何东西,因为单词字符永远不能同时跟在非单词和单词字符后面。

\B

匹配非字边界。这是前一个字符和下一个字符类型相同的位置:要么两个字符都必须是单词,要么两个字符都必须是非单词。例如在两个字母之间或两个空格之间。字符串的开头和结尾被视为非单词。与匹配的单词边界相同,匹配的非单词边界也不包括在匹配中。

例如,

  • /\Bon/匹配at noon中的on
  • /ye\B/匹配possibly yesterday中的ye

浏览器兼容性

您还可以使用数字格式构造函数。以下是您如何做到这一点。

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

我的答案是唯一一个用更明智的替代方案完全取代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。

请记住,在评论区,过度的赞美被认为是离题的。相反,只要给我投赞成票就行了。

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

  • 使用RegEx(快速准确)
  • 支持数字(浮点数/整数)/字符串/字符串中的多个数字
  • 智能井(不分组小数-兼容不同类型的分组)
  • 支持所有浏览器,特别是“Safari”和“IE”以及许多较旧的浏览器
  • [可选]尊重非英语(波斯/阿拉伯语)数字(+前缀)
太长别读-完整版本功能(缩小):

// num: Number/s (String/Number),// sep: Thousands separator (String) - Default: ','// dec: Decimal separator (String) - Default: '.' (Just one char)// u: Universal support for languages characters (String - RegEx character set / class) - Example: '[\\d\\u0660-\\u0669\\u06f0-\\u06f9]' (English/Persian/Arabic), Default: '\\d' (English)
function 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 English or Persian/Arabic ۱۲۳۴۵۶۷۸۹/٠١٢٣٤٥٦٧٨٩ this is 123123123.123123123 with this -123123 and these 10 100 1000 123123/123123 (2000000) .33333 100.00 or any like 500000Kg';
console.log(formatNums(10000000.0012));console.log(formatNums(10000000.0012,'.',',')); // Germanconsole.log(formatNums(text,',','.','[\\d\\u0660-\\u0669\\u06f0-\\u06f9]')); // Respect Persian/Arabic digits
<input oninput="document.getElementById('result').textContent=formatNums(this.value)" placeholder="Type a number here"><div id="result"></div>

为什么不满意其他答案?

  • Number.prototype.toLocaleString()/int. NumberFormat(正确答案)
    • 如果没有好的参数,我们不能期待同样的结果。还有参数选项,我们仍然无法确定结果是什么,因为它将使用本地设置和可能的客户端修改效果,或者浏览器/设备不支持它。
    • >~2016浏览器支持并且仍然在2021年,一些报告在某些情况下,如SafariIE/Edge没有按预期返回。
    • toLocaleString()使用数字,Intl.NumberFormat使用字符串/数字;字符串将/必须被解析,必要时也被舍入,所以:
      • 如果我们已经有一个带有non-English digits的本地化字符串,我们必须用英文字符串替换数字,然后解析它,然后再次使用它和本地选项。(如果它返回我们期望的)
      • 一般来说,在解析时,我们不能期望不是missing decimal zerosbig numbers中的细节或尊重other languages numeral characters
    • 十进制/千分隔符字符不能自定义超过语言选项,除非使用后固定替换()+RegEx再次。(例如在波斯语中,我们通常不使用建议的阿拉伯逗号,有时我们也使用#0分数/除法斜杠作为小数分隔符)
    • 循环中的缓慢性能
  • 不太好的RegEx方式(最快和单行方式)
    • /\B(?=(\d{3})+\b)/它也会对小数进行分组。// 123,123.123,123 !!!
    • /(?<!\.\d+)\B(?=(\d{3})+\b)/使用了尚不支持的后看。请检查:
      https://caniuse.com/js-regexp-lookbehind
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#browser_compatibility
      注意:通常,lookback可以针对原始RegEx结构(因为分析器应该如何工作,比如不要将原始数据作为解析器缓冲),实际上它可以使性能严重降低(在这种情况下~30%)。我认为随着时间的推移,它被请求推向了内部。
    • /\B(?=(?=\d*\.)(\d{3})+(?!\d))/只处理浮点数并忽略整数。
    • .replace(/(?:[^.\d]|^)\d+/g,function(a){return a.replace(/\B(?=(?:\d{3})+\b)/g,',');})(我的老想法)使用2个正则表达式。第一个找到整数部分,第二个放分隔符。为什么2个函数,当它可以混合时?
    • /(\..*)$|(\d)(?=(\d{3})+(?!\d))/g@陈志立的好主意-我投了赞成票),但当RegEx是全球性的时,(\..*)$即使最后有空格也会出错。使用捕获组(示例:#0)也会使性能降低,所以如果可能的话,使用非捕获组(例:#1),或者如果我们的函数中已经存在语句,让我们混合它。
      在这种情况下,不使用捕获组可以提高约20%的性能,而在/\B(?=(\d{3})+\b)/g/\B(?=(?:\d{3})+\b)/g的情况下,第二个组的性能提高了约8%。关于regex性能:https://jsben.ch/HUmDA注意:当然不同的方法、浏览器、硬件、系统状态、案例甚至ECMAScript上的更改都会影响检查性能的结果。但是一些逻辑上的变化应该会影响结果,我用这个作为视觉示例。
  • 使用库就像Numeral.js没有必要的功能来完成一个简单的任务。
  • 使用.split('.').toFixed()Math.floor()的重代码/不准确函数…

最终结果:

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

  1. 兼容性
  2. 能力
  3. 普遍性
  4. 易用性
  5. 性能

toLocaleString()(兼容性-普遍性)[本机函数]

  • 如果您必须将数字和分组从英语更改为另一种语言
  • 如果你不确定你的客户语言
  • 如果你不需要确切的预期结果
  • 如果你不关心旧版本的Safari
// 1000000.2301parseFloat(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.2301new Intl.NumberFormat('en-US', { // It can be 'fa-IR' : Farsi - IrannumberingSystem: '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 defaultssep = sep || ','; // Seperatoru = 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 stringif (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 digitsfunction(a) { // Any match can be the decimal part or the integer part so lets check itreturn 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.})}

function 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('۱۲۳۴۵۶۷۸۹/۹۰۰۰',',','/','[\\d\\u0660-\\u0669\\u06f0-\\u06f9]'));

在这里播放示例:https://jsfiddle.net/PAPIONbit/198xL3te/

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

function 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,' '));

检查RegEx(没有必要的功能):https://regexr.com/66ott

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

如果输入是指定/预定义的,最好选择。(像通常的价格一样,肯定不会超过3个小数)(比toLocaleString快约65%)

num=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 Englishn.replace(/[\u0660-\u0669\u06f0-\u06f9]/g, // RegEx unicode range Persian/Arabic numbers charfunction(c) {return c.charCodeAt(0) & 0xf; // Replace the char with real number by getting the binary index and breaking to lowest using 15});}// 1234567890

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


我的老学校功能在这篇文章中:(比toLocalString快约15%)

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

我对这个问题的答案数量印象深刻。我喜欢uKolka的答案:

n.toLocaleString()

但不幸的是,在西班牙语等某些语言环境中,对于低于10,000的数字,它不起作用(IMHO):

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

给出1000而不是1.000

看看toLocaleString在所有浏览器中不适用于小于10000的数字就知道为什么了。

所以我必须使用EliasZamaria的答案来选择正确的千分隔符:

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.567let decimals = 2let 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。)

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

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

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

例如,x=12345678.12345678将给出格式化='12,345,678.12345678'。

您可以在数字原型上创建一个函数

Number.prototype.format = function (s, d) {return (this.toString().split(".").map((n, i) =>i? n: n.split("").map((n, i) => (i % 3 || !i ? n : s + n)).join("")).join(d));};
console.log((8800.00).format(',', '.'))// 8,880.00
// French notationconsole.log((8800.00).format(' ', ','))// 8 880,00

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

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
let formatNumber = (number) => {let str = String(number)
return str.split('').reduce((a, b, i) => a + (i && !((str.length - i) % 3) ? ',' : '') + b,'')}

与@elias-zamaria和@t.j.crowder相关

Safari浏览器的负面后视是不能使用<。所以,它将是(?!\.\d*)

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

适用于Safari和Firefox

这是一个简单的可重用函数,它返回一个具有指定小数位数的字符串,并允许您切换逗号的包含。

function format_number(number, num_decimals, include_comma){return number.toLocaleString('en-US', {useGrouping: include_comma, minimumFractionDigits: num_decimals, maximumFractionDigits: num_decimals});}

使用示例:

format_number(1234.56789, 2, true); // Returns '1,234.57'format_number(9001.42, 0, false); // Returns '9001'

如果您需要进一步自定义字符串,您可以找到格式化选项列表这里

我之前在某个地方找到了这个答案,我更新了它以允许负数。

// Keep only digits, hyphen  and decimal points:myNum   .replace(/[^-\d.]/g, "")// Remove duplicated decimal point, if one exists:.replace(/^(\d*\.)(.*)\.(.*)$/, '$1$2$3')// Keep only two digits past the decimal point:.replace(/\.(\d{2})\d+/, '.$1')// Add thousands separators:.replace(/\B(?=(\d{3})+(?!\d))/g, ",")

另一种复杂度为n(Math.floor(str.length / 3))而不是n(str.length)的方法

function formatNumber(num) {let str = String(num)  
if (num < 1000) return str
let result = ''
for (let i = Math.floor(str.length / 3); i >= 0; i--) {let start = str.length - 3 * (i + 1)let end = start + 3
result +=(end ? str.slice(Math.max(0, start), end) : '') + (end && i ? ',' : '')}
return result}

我挑战另一个解决方案。

第一个代码是这样的。

function formatNumber(number) {if (number < 1000) {return String(number);}if (number < 1000000) {let numbers = String(number).split('');numbers.splice(-3, 0, ',');return numbers.join('');}if (number < 1000000000) {let numbers = String(number).split('');numbers.splice(-3, 0, ',');numbers.splice(-7, 0, ',');return numbers.join('');}if (number < 1000000000000) {let numbers = String(number).split('');numbers.splice(-3, 0, ',');numbers.splice(-7, 0, ',');numbers.splice(-11, 0, ',');return numbers.join('');}
throw new Error(`number: ${number} is too big`);}

这段代码很长且不可扩展,但它是有效的,因为它检查数字本身而不是从数字转换的字符串长度。

所以我基于这个想法转换为整洁的代码。(您可以将12做得更大以防止错误。)

function formatNumber(number) {let commas = -1;for (let n3 = 3; n3 <= 12; n3 += 3) {commas++;const max = Math.pow(10, n3);if (number < max) {let numbers = String(number).split('');for (let i = 0; i < commas; i++) {numbers.splice(-(3 * (i + 1) + i), 0, ',');}return numbers.join('');}}
throw new Error(`number: ${number} is too big`);}