I am trying to print an integer in JavaScript with commas as thousands separators. For example, I want to show the number 1234567 as "1,234,567". How would I go about doing this?
我正在尝试用JavaScript打印一个整数,并用逗号作为数千个分隔符。例如,我想将数字1234567显示为“1,234,567”。我该怎么做呢?
Here is how I am doing it:
我是这样做的:
function numberWithCommas(x) {
x = x.toString();
var pattern = /(-?\d+)(\d{3})/;
while (pattern.test(x))
x = x.replace(pattern, "$1,$2");
return x;
}
Is there a simpler or more elegant way to do it? It would be nice if it works with floats also, but that is not necessary. It does not need to be locale-specific to decide between periods and commas.
有更简单或更优雅的方法吗?如果它也能与浮点数一起工作,那就太好了,但这不是必须的。在句点和逗号之间,不需要特定于地区。
42 个解决方案
#1
1978
I used the idea from Kerry's answer, but simplified it since I was just looking for something simple for my specific purpose. Here is what I did:
我使用了克里的答案中的想法,但简化了它,因为我只是在寻找一些简单的东西来达到我的特定目的。我所做的是:
const numberWithCommas = (x) => {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
This is all you really need to know.
这就是你真正需要知道的。
@Neils Bom asked how the regex works. My explanation is sort of long. It won't fit in the comments and I don't know where else to put it so I am doing it here. If anyone has any other suggestions for where to put it, please let me know.
neils Bom问regex是如何工作的。我的解释有点长。它不适合在评论中,我不知道还能放在哪里,所以我在这里写。如果有人有其他的建议,请告诉我。
The regex uses 2 lookahead assertions: a positive one to look for any point in the string that has a multiple of 3 digits in a row after it, and a negative assertion to make sure that point only has exactly a multiple of 3 digits. The replacement expression puts a comma there.
regex使用两个前视断言:一个是正的断言,用于查找字符串中在其后一行中有3位数的任何点,另一个是负的断言,以确保该点只有3位数的倍数。替换表达式在那里放一个逗号。
For example, if you pass it "123456789.01", the positive assertion will match every spot to the left of the 7 (since "789" is a multiple of 3 digits, "678" is a multiple of 3 digits, "567", etc.). The negative assertion checks that the multiple of 3 digits does not have any digits after it. "789" has a period after it so it is exactly a multiple of 3 digits, so a comma goes there. "678" is a multiple of 3 digits but it has a "9" after it, so those 3 digits are part of a group of 4, and a comma does not go there. Similarly for "567". "456789" is 6 digits, which is a multiple of 3, so a comma goes before that. "345678" is a multiple of 3, but it has a "9" after it, so no comma goes there. And so on. The "\B" keeps the regex from putting a comma at the beginning of the string.
例如,如果您传递的是“123456789.01”,那么积极的断言将匹配7(因为“789”是3位数字的倍数,“678”是3位数字的倍数,“567”等)。负断言检查3位数字的倍数后没有任何数字。"789"后面有一个句号所以它是3位数的倍数,所以这里有一个逗号。“678”是3位数字的倍数,但后面有一个“9”,所以这3位数字是4组数字的一部分,而逗号不在这里。同样为“567”。"456789"是6位数字,是3的倍数,所以前面加一个逗号。“345678”是3的倍数,但是后面有个“9”,所以没有逗号。等等。“\B”使正则表达式在字符串开始时不加逗号。
@neu-rah mentioned that this function adds commas in undesirable places if there are more than 3 digits after the decimal point. If this is a problem, you can use this function:
@ neurah提到,如果小数点后超过3位,则此函数在不希望出现的地方添加逗号。如果这是一个问题,你可以使用这个功能:
const numberWithCommas = (x) => {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
#2
998
I'm surprised nobody mentioned Number.prototype.toLocaleString. It's implemented in JavaScript 1.5 (which was introduced in 1999) so it's basically supported across major browsers.
我很惊讶没人提到number。prototype。tolocalestring。它是在JavaScript 1.5中实现的(在1999年引入),因此基本上在主要浏览器中都是受支持的。
var n = 34523453.345
n.toLocaleString()
"34,523,453.345"
It also works in Node.js as of v0.12 via inclusion of Intl
它也适用于Node。js通过包含Intl来实现v0.12。
If you want something different, Numeral.js might be interesting.
如果你想要不同的数字。js可能会很有趣。
#3
165
var number = 1234567890; // Example number to be converted
⚠ Mind that javascript has a maximum integer value of 9007199254740991
⚠介意javascript的最大整数值9007199254740991
toLocaleString:
number.toLocaleString(); // "1,234,567,890"
// A more complex example:
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"
NumberFormat (Safari not supported):
NumberFormat(Safari浏览器不支持):
var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"
From what I checked (Firefox at least) they are both more or less same regarding performance.
从我检查过的(至少是Firefox)来看,它们在性能上或多或少是相同的。
#4
83
I suggest using phpjs.org 's number_format()
我建议使用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);
}
UPDATE 02/13/14
更新02/13/14
People have been reporting this doesn't work as expected, so I did a JS Fiddle that includes automated tests.
人们一直在报告这并不像预期的那样工作,所以我做了一个包含自动测试的JS Fiddle。
Update 26/11/2017
更新26/11/2017
Here's that fiddle as a Stack Snippet with slightly modified output:
这是一个稍作修改的输出作为堆栈片段的小提琴:
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);
}
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;
}
#5
64
This is a variation of @mikez302's answer, but modified to support numbers with decimals (per @neu-rah's feedback that numberWithCommas(12345.6789) -> "12,345.6,789" instead of "12,345.6789"
这是@mikez302答案的一个变体,但是修改为支持小数(根据@neu-rah的反馈,该数字与逗号(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] : "");
}
#6
54
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
#7
31
Thanks to everyone for their replies. I have built off of some of the answers to make a more "one-size-fits-all" solution.
谢谢大家的回复。我已经从一些答案中构建出了更“一刀切”的解决方案。
The first snippet adds a function that mimics PHP's number_format()
to the Number prototype. If I am formatting a number, I usually want decimal places so the function takes in the number of decimal places to show. Some countries use commas as the decimal and decimals as the thousands separator so the function allows these separators to be set.
第一个代码片段向数字原型添加了一个模仿PHP的number_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);
}
You would use this as follows:
你可以这样使用:
var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00
I found that I often needed to get the number back for math operations, but parseFloat converts 5,000 to 5, simply taking the first sequence of integer values. So I created my own float conversion function and added it to the String prototype.
我发现我经常需要返回数字进行数学运算,但是parseFloat将5000转换为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));
}
Now you can use both functions as follows:
现在你可以同时使用这两个功能如下:
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
#8
21
I think this is the shortest regular expression that does it:
我认为这是最短的正则表达式
/\B(?=(\d{3})+\b)/g
"123456".replace(/\B(?=(\d{3})+\b)/g, ",")
I checked it on a few numbers and it worked.
我在几个数字上查了一下,它是有效的。
#9
21
Intl.NumberFormat
Native JS function. Supported by IE11, Edge, latest Safari, Chrome, Firefox, Opera, Safari on iOS and Chrome on Android.
本地javascript函数。支持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
#10
18
Number.prototype.toLocaleString()
would have been awesome if it was provided natively by all browsers (Safari).
如果它是由所有浏览器(Safari)提供的,那么Number.prototype.toLocaleString()将会非常棒。
I checked all other answers but noone seemed to polyfill it. Here is a poc towards that, which is actually a combination of first two answers; if toLocaleString
works it uses it, if it doesn't it uses a custom function.
我检查了所有的答案,但似乎没有人多填。这是一个poc,实际上是前两个答案的组合;如果toLocaleString工作它使用它,如果它不使用自定义函数。
var putThousandsSeparators;
putThousandsSeparators = function(value, sep) {
if (sep == null) {
sep = ',';
}
// check if it needs formatting
if (value.toString() === value.toLocaleString()) {
// split decimals
var parts = value.toString().split('.')
// format whole numbers
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
// put them back together
value = parts[1] ? parts.join('.') : parts[0];
} else {
value = value.toLocaleString();
}
return value;
};
alert(putThousandsSeparators(1234567.890));
#11
15
The thousands separator can be inserted in an international-friendly manner using the browser's Intl
object:
可以使用浏览器的Intl对象以国际化友好的方式插入数千个分隔符:
Intl.NumberFormat().format(1234);
// returns "1,234" if the user's locale is en_US, for example
See MDN's article on NumberFormat for more, you can specify locale behavior or default to the user's. This is a little more foolproof because it respects local differences; many countries use periods to separate digits while a comma denotes the decimals.
更多信息请参见MDN关于NumberFormat的文章,您可以指定用户的语言环境行为或默认语言环境。这更简单,因为它尊重当地的差异;许多国家使用周期来分隔数字,而逗号表示小数。
Intl.NumberFormat isn't available in all browsers yet, but it works in latest Chrome, Opera, & IE. Firefox's next release should support it. Webkit doesn't seem to have a timeline for implementation.
Intl。数字格式并不是所有浏览器都可以使用,但是它可以在最新的Chrome, Opera和IE中使用。Firefox的下一个版本应该支持它。Webkit似乎没有实现的时间表。
#12
13
if you are dealing with currency values and formatting a lot then it might be worth to add tiny accounting.js which handles lot of edge cases and localization:
如果您正在处理大量的货币值和格式化,那么添加微小的记帐是值得的。处理很多边缘案例和本地化的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
#13
12
The following code uses char scan, so there's no regex.
下面的代码使用char扫描,所以没有regex。
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] : '');
}
It shows promising performance: http://jsperf.com/number-formatting-with-commas/5
它显示了良好的性能:http://jsperf.com/number-formatting-with-commas/5
2015.4.26: Minor fix to resolve issue when num<0. See https://jsfiddle.net/runsun/p5tqqvs3/
2015.4.26:小修正当num<0时解决问题。参见https://jsfiddle.net/runsun/p5tqqvs3/
#14
8
Here's a simple function that inserts commas for thousand separators. It uses array functions rather than a 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('');
};
#15
7
I Wrote this one before stumbling on this post. No regex and you can actually understand the code.
在偶然发现这篇文章之前,我写了这篇文章。没有regex,您实际上可以理解代码。
$(function(){
function insertCommas(s) {
// get stuff before the dot
var d = s.indexOf('.');
var s2 = d === -1 ? s : s.slice(0, d);
// insert commas every 3 digits from the right
for (var i = s2.length - 3; i > 0; i -= 3)
s2 = s2.slice(0, i) + ',' + s2.slice(i);
// append fractional part
if (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>
#16
7
You can either use this procedure to format your currency needing.
您可以使用此过程来格式化您需要的货币。
var nf = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’
For more info you can access this link.
更多信息,你可以访问这个链接。
https://www.justinmccandless.com/post/formatting-currency-in-javascript/
https://www.justinmccandless.com/post/formatting-currency-in-javascript/
#17
6
Let me try to improve uKolka's answer and maybe help others save some time.
让我试着改进uKolka的答案,也许可以帮助其他人节省一些时间。
Use Numeral.js.
使用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>
You should go with Number.prototype.toLocaleString() only if its browser compatibilty is not an issue.
只有当它的浏览器兼容并不是问题时,才应该使用Number.prototype.toLocaleString()。
#18
5
For me, the best answer is using toLocaleString like some members said. If you want to include the '$' symbol just add languaje and type options. Here is and example to format a number to Mexican Pesos
对我来说,最好的答案是像一些成员说的那样使用toLocaleString。如果要包含“$”符号,只需添加语言和类型选项。这里是将数字格式化为墨西哥比索的例子
var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))
shortcut
快捷方式
1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})
#19
4
I think this function will take care of all the issues related to this problem.
我认为这个函数将处理与这个问题相关的所有问题。
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;
}
#20
3
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(".");
}
#21
2
I think your solution is one of the shorter ones I've seen for this. I don't think there are any standard JavaScript functions to do this sort of thing, so you're probably on your own.
我认为你的解决方案是我见过的较短的方案之一。我不认为有任何标准的JavaScript函数可以做这种事情,所以您可能需要自己做。
I checked the CSS 3 specifications to see whether it's possible to do this in CSS, but unless you want every digit in its own <span>
, I don't think that's possible.
我检查了CSS 3规范,看看是否有可能在CSS中这样做,但是除非您希望每个数字都在自己的中,否则我认为这是不可能的。
I did find one project on Google Code that looked promising: flexible-js-formatting. I haven't used it, but it looks pretty flexible and has unit tests using JsUnit. The developer also has a lot of posts (though old) about this topic.
我发现谷歌代码中有一个项目看起来很有前途:灵活的js格式。我还没有使用它,但是它看起来非常灵活,并且有使用JsUnit的单元测试。开发人员也有很多关于这个主题的帖子(虽然老了)。
Be sure to consider international users: lots of nations use a space as the separator and use the comma for separating the decimal from the integral part of the number.
一定要考虑到国际用户:许多国家使用空格作为分隔符,并使用逗号将小数部分与整数部分分开。
#22
2
Lots of good answers already. Here's another, just for fun:
已经有很多好的答案了。这是另一个,只是为了好玩:
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 - 1
return num + (pos && !(pos % 3) ? "," : "") + acc;
}, "") + (p[1] ? "." + p[1] : "");
}
Some examples:
一些例子:
format(77.03453, 2); // "77.03"
format(78436589374); // "78,436,589,374"
format(784, 4); // "784.0000"
format(-123456); // "-123,456"
#23
2
Here's my try:
这是我的尝试:
EDIT: Added in decimals
编辑:在小数补充道
function splitMille(n, separator = ',') {
// Cast to string
let 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 numbers
decimals = num.replace(/^.*(\..*)$/, '$1')
}
// Remove decimals from the number string
num = 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 number
return `${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)
#24
1
I added tofixed to Aki143S's solution. This solution uses dots for thousands separators and comma for the precision.
我在Aki143S的解决方案中添加了tofixed。这个解决方案在数千个分隔符和逗号中使用点作为精度。
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('');
};
Examples;
的例子;
formatNumber(17347, 0) = 17.347
formatNumber(17347, 3) = 17.347,000
formatNumber(1234563.4545, 3) = 1.234.563,454
#25
1
The solution from @user1437663 is great.
@user1437663的解决方案很棒。
Who really understands the solution is being prepared to understand complex regular expressions.
真正理解解决方案的人是准备理解复杂的正则表达式。
A small improvement to make it more readable:
一个小的改进使它更可读:
function numberWithCommas(x) {
var parts = x.toString().split(".");
return parts[0].replace(/\B(?=(\d{3})+(?=$))/g, ",") + (parts[1] ? "." + parts[1] : "");
}
The pattern starts with \B to avoid use comma at the beginning of a word. Interestingly, the pattern is returned empty because \B does not advance the "cursor" (the same applies to $).
模式以\B开头,避免在单词的开头使用逗号。有趣的是,模式返回为空,因为\B不推进“游标”(同样适用于$)。
O \B is followed by a less known resources but is a powerful feature from Perl's regular expressions.
O \B后面跟着一个鲜为人知的资源,但它是Perl正则表达式的一个强大特性。
Pattern1 (? = (Pattern2) ).
The magic is that what is in parentheses (Pattern2) is a pattern that follows the previous pattern (Pattern1) but without advancing the cursor and also is not part of the pattern returned. It is a kind of future pattern. This is similar when someone looks forward but really doesn't walk!
其神奇之处在于,圆括号(Pattern2)中的模式遵循了前面的模式(Pattern1),但是没有向前移动光标,也不是返回模式的一部分。这是一种未来的模式。当一个人向前看却真的不走的时候,这是相似的!
In this case pattern2 is
在这种情况下,模式n2是
\d{3})+(?=$)
It means 3 digits (one or more times) followed by the end of the string ($)
它的意思是3位数字(一个或多个)后面跟着字符串的末尾($)
Finally, Replace method changes all occurrences of the pattern found (empty string) for comma. This only happens in cases where the remaining piece is a multiple of 3 digits (such cases where future cursor reach the end of the origin).
最后,Replace方法将更改为逗号找到的所有模式(空字符串)。这种情况只发生在剩余部分是3位数字的倍数的情况下(这种情况下,未来的游标到达原点的末端)。
#26
1
Here is good solution with less coding...
这里有一个好的解决方案,少编码……
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 += ",";
}
#27
1
An alternative way, supporting decimals, different separators and negatives.
另一种方法,支持小数,不同的分隔符和负号。
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.abs(Math.ceil(number)).toString()
, i = n.length % 3
, f = n.substr(0, i)
;
if(number < 0) f = '-' + f;
for(;i<n.length;i+=3) {
if(i!=0) f+=ts;
f+=n.substr(i,3);
}
if(dp > 0)
f += ds + number.toFixed(dp).split('.')[1]
return f;
}
#28
1
I've adapted your code to work in TextBox (Input type="text") so we can enter and delete digits in real time without losing cursor. It's works also if you select range when you delete. And you can use arrows and home/end buttons freely.
Thanks for saving my time!
我修改了您的代码,使其在文本框(Input type="text")中工作,这样我们就可以在不丢失光标的情况下实时输入和删除数字。如果你在删除的时候选择range,它也可以工作。你可以*地使用箭头和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-keys
var selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positions
var 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 button
var delPos = parts[0].search(/\d{4}/);
if (delPos != -1) {//if found 4 digits in a row (',' is deleted)
if (e.keyCode == 8) {//if backspace flag
parts[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.443216
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digits
if (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;
}
To use this just added two events - onKeyUp and onKeyDown
要使用它,只需添加两个事件——onKeyUp和onKeyDown
<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>
#29
1
I thought I'd share a little trick which I'm using for large number formatting. Instead of inserting commas or spaces, I insert an empty but visible span in between the "thousands". This makes thousands easily visible, but it allows to copy/paste the input in the original format, without commas/spaces.
我想分享一个小技巧,我用它来进行大量的格式化。我没有插入逗号或空格,而是在“千”之间插入一个空但可见的跨度。这使得数以千计的输入很容易可见,但是它允许以原始格式复制/粘贴输入,而不需要逗号/空格。
// 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 present
var period = orgVal.indexOf(".");
var frac = period >= 0 ? orgVal.substr(period) : "";
// Work on input as an integer
var 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 information
res += frac;
return res;
}
With this CSS:
这个CSS:
.thousandsSeparator {
display : inline;
padding-left : 4px;
}
See an example JSFiddle.
看到一个JSFiddle例子。
#30
1
After not finding a modern and comprehensive solution here, I have written an arrow function (without regex) to solve the formatting problem and it allows the caller to provide number of fraction digits as well as the period and thousand separator for Europe and rest of the world.
在这里没有找到一个现代的、全面的解决方案之后,我编写了一个箭头函数(没有regex)来解决格式问题,它允许调用者为欧洲和世界其他地区提供小数位数、周期和千分隔符。
Examples:
例子:
numberFormatter(1234567890.123456) => 1,234,567,890 numberFormatter(1234567890.123456, 4) => 1,234,567,890.1235 numberFormatter(1234567890.123456, 4, '.', ',') => 1.234.567.890,1235 Europe
Here is the function written in ES6 (modern syntax):
下面是用ES6(现代语法)编写的函数:
const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => {
if (number!==0 && !number || !Number.isFinite(number)) return number
const frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0
const 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] : ''}`
}
It has been tested for negative, bad input and NaN cases. If the input is NaN then it simply returns it.
已检测为阴性、不良输入和NaN病例。如果输入是NaN,那么它只返回它。
#1
1978
I used the idea from Kerry's answer, but simplified it since I was just looking for something simple for my specific purpose. Here is what I did:
我使用了克里的答案中的想法,但简化了它,因为我只是在寻找一些简单的东西来达到我的特定目的。我所做的是:
const numberWithCommas = (x) => {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
This is all you really need to know.
这就是你真正需要知道的。
@Neils Bom asked how the regex works. My explanation is sort of long. It won't fit in the comments and I don't know where else to put it so I am doing it here. If anyone has any other suggestions for where to put it, please let me know.
neils Bom问regex是如何工作的。我的解释有点长。它不适合在评论中,我不知道还能放在哪里,所以我在这里写。如果有人有其他的建议,请告诉我。
The regex uses 2 lookahead assertions: a positive one to look for any point in the string that has a multiple of 3 digits in a row after it, and a negative assertion to make sure that point only has exactly a multiple of 3 digits. The replacement expression puts a comma there.
regex使用两个前视断言:一个是正的断言,用于查找字符串中在其后一行中有3位数的任何点,另一个是负的断言,以确保该点只有3位数的倍数。替换表达式在那里放一个逗号。
For example, if you pass it "123456789.01", the positive assertion will match every spot to the left of the 7 (since "789" is a multiple of 3 digits, "678" is a multiple of 3 digits, "567", etc.). The negative assertion checks that the multiple of 3 digits does not have any digits after it. "789" has a period after it so it is exactly a multiple of 3 digits, so a comma goes there. "678" is a multiple of 3 digits but it has a "9" after it, so those 3 digits are part of a group of 4, and a comma does not go there. Similarly for "567". "456789" is 6 digits, which is a multiple of 3, so a comma goes before that. "345678" is a multiple of 3, but it has a "9" after it, so no comma goes there. And so on. The "\B" keeps the regex from putting a comma at the beginning of the string.
例如,如果您传递的是“123456789.01”,那么积极的断言将匹配7(因为“789”是3位数字的倍数,“678”是3位数字的倍数,“567”等)。负断言检查3位数字的倍数后没有任何数字。"789"后面有一个句号所以它是3位数的倍数,所以这里有一个逗号。“678”是3位数字的倍数,但后面有一个“9”,所以这3位数字是4组数字的一部分,而逗号不在这里。同样为“567”。"456789"是6位数字,是3的倍数,所以前面加一个逗号。“345678”是3的倍数,但是后面有个“9”,所以没有逗号。等等。“\B”使正则表达式在字符串开始时不加逗号。
@neu-rah mentioned that this function adds commas in undesirable places if there are more than 3 digits after the decimal point. If this is a problem, you can use this function:
@ neurah提到,如果小数点后超过3位,则此函数在不希望出现的地方添加逗号。如果这是一个问题,你可以使用这个功能:
const numberWithCommas = (x) => {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
#2
998
I'm surprised nobody mentioned Number.prototype.toLocaleString. It's implemented in JavaScript 1.5 (which was introduced in 1999) so it's basically supported across major browsers.
我很惊讶没人提到number。prototype。tolocalestring。它是在JavaScript 1.5中实现的(在1999年引入),因此基本上在主要浏览器中都是受支持的。
var n = 34523453.345
n.toLocaleString()
"34,523,453.345"
It also works in Node.js as of v0.12 via inclusion of Intl
它也适用于Node。js通过包含Intl来实现v0.12。
If you want something different, Numeral.js might be interesting.
如果你想要不同的数字。js可能会很有趣。
#3
165
var number = 1234567890; // Example number to be converted
⚠ Mind that javascript has a maximum integer value of 9007199254740991
⚠介意javascript的最大整数值9007199254740991
toLocaleString:
number.toLocaleString(); // "1,234,567,890"
// A more complex example:
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"
NumberFormat (Safari not supported):
NumberFormat(Safari浏览器不支持):
var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"
From what I checked (Firefox at least) they are both more or less same regarding performance.
从我检查过的(至少是Firefox)来看,它们在性能上或多或少是相同的。
#4
83
I suggest using phpjs.org 's number_format()
我建议使用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);
}
UPDATE 02/13/14
更新02/13/14
People have been reporting this doesn't work as expected, so I did a JS Fiddle that includes automated tests.
人们一直在报告这并不像预期的那样工作,所以我做了一个包含自动测试的JS Fiddle。
Update 26/11/2017
更新26/11/2017
Here's that fiddle as a Stack Snippet with slightly modified output:
这是一个稍作修改的输出作为堆栈片段的小提琴:
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);
}
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;
}
#5
64
This is a variation of @mikez302's answer, but modified to support numbers with decimals (per @neu-rah's feedback that numberWithCommas(12345.6789) -> "12,345.6,789" instead of "12,345.6789"
这是@mikez302答案的一个变体,但是修改为支持小数(根据@neu-rah的反馈,该数字与逗号(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] : "");
}
#6
54
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
#7
31
Thanks to everyone for their replies. I have built off of some of the answers to make a more "one-size-fits-all" solution.
谢谢大家的回复。我已经从一些答案中构建出了更“一刀切”的解决方案。
The first snippet adds a function that mimics PHP's number_format()
to the Number prototype. If I am formatting a number, I usually want decimal places so the function takes in the number of decimal places to show. Some countries use commas as the decimal and decimals as the thousands separator so the function allows these separators to be set.
第一个代码片段向数字原型添加了一个模仿PHP的number_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);
}
You would use this as follows:
你可以这样使用:
var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00
I found that I often needed to get the number back for math operations, but parseFloat converts 5,000 to 5, simply taking the first sequence of integer values. So I created my own float conversion function and added it to the String prototype.
我发现我经常需要返回数字进行数学运算,但是parseFloat将5000转换为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));
}
Now you can use both functions as follows:
现在你可以同时使用这两个功能如下:
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
#8
21
I think this is the shortest regular expression that does it:
我认为这是最短的正则表达式
/\B(?=(\d{3})+\b)/g
"123456".replace(/\B(?=(\d{3})+\b)/g, ",")
I checked it on a few numbers and it worked.
我在几个数字上查了一下,它是有效的。
#9
21
Intl.NumberFormat
Native JS function. Supported by IE11, Edge, latest Safari, Chrome, Firefox, Opera, Safari on iOS and Chrome on Android.
本地javascript函数。支持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
#10
18
Number.prototype.toLocaleString()
would have been awesome if it was provided natively by all browsers (Safari).
如果它是由所有浏览器(Safari)提供的,那么Number.prototype.toLocaleString()将会非常棒。
I checked all other answers but noone seemed to polyfill it. Here is a poc towards that, which is actually a combination of first two answers; if toLocaleString
works it uses it, if it doesn't it uses a custom function.
我检查了所有的答案,但似乎没有人多填。这是一个poc,实际上是前两个答案的组合;如果toLocaleString工作它使用它,如果它不使用自定义函数。
var putThousandsSeparators;
putThousandsSeparators = function(value, sep) {
if (sep == null) {
sep = ',';
}
// check if it needs formatting
if (value.toString() === value.toLocaleString()) {
// split decimals
var parts = value.toString().split('.')
// format whole numbers
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
// put them back together
value = parts[1] ? parts.join('.') : parts[0];
} else {
value = value.toLocaleString();
}
return value;
};
alert(putThousandsSeparators(1234567.890));
#11
15
The thousands separator can be inserted in an international-friendly manner using the browser's Intl
object:
可以使用浏览器的Intl对象以国际化友好的方式插入数千个分隔符:
Intl.NumberFormat().format(1234);
// returns "1,234" if the user's locale is en_US, for example
See MDN's article on NumberFormat for more, you can specify locale behavior or default to the user's. This is a little more foolproof because it respects local differences; many countries use periods to separate digits while a comma denotes the decimals.
更多信息请参见MDN关于NumberFormat的文章,您可以指定用户的语言环境行为或默认语言环境。这更简单,因为它尊重当地的差异;许多国家使用周期来分隔数字,而逗号表示小数。
Intl.NumberFormat isn't available in all browsers yet, but it works in latest Chrome, Opera, & IE. Firefox's next release should support it. Webkit doesn't seem to have a timeline for implementation.
Intl。数字格式并不是所有浏览器都可以使用,但是它可以在最新的Chrome, Opera和IE中使用。Firefox的下一个版本应该支持它。Webkit似乎没有实现的时间表。
#12
13
if you are dealing with currency values and formatting a lot then it might be worth to add tiny accounting.js which handles lot of edge cases and localization:
如果您正在处理大量的货币值和格式化,那么添加微小的记帐是值得的。处理很多边缘案例和本地化的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
#13
12
The following code uses char scan, so there's no regex.
下面的代码使用char扫描,所以没有regex。
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] : '');
}
It shows promising performance: http://jsperf.com/number-formatting-with-commas/5
它显示了良好的性能:http://jsperf.com/number-formatting-with-commas/5
2015.4.26: Minor fix to resolve issue when num<0. See https://jsfiddle.net/runsun/p5tqqvs3/
2015.4.26:小修正当num<0时解决问题。参见https://jsfiddle.net/runsun/p5tqqvs3/
#14
8
Here's a simple function that inserts commas for thousand separators. It uses array functions rather than a 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('');
};
#15
7
I Wrote this one before stumbling on this post. No regex and you can actually understand the code.
在偶然发现这篇文章之前,我写了这篇文章。没有regex,您实际上可以理解代码。
$(function(){
function insertCommas(s) {
// get stuff before the dot
var d = s.indexOf('.');
var s2 = d === -1 ? s : s.slice(0, d);
// insert commas every 3 digits from the right
for (var i = s2.length - 3; i > 0; i -= 3)
s2 = s2.slice(0, i) + ',' + s2.slice(i);
// append fractional part
if (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>
#16
7
You can either use this procedure to format your currency needing.
您可以使用此过程来格式化您需要的货币。
var nf = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’
For more info you can access this link.
更多信息,你可以访问这个链接。
https://www.justinmccandless.com/post/formatting-currency-in-javascript/
https://www.justinmccandless.com/post/formatting-currency-in-javascript/
#17
6
Let me try to improve uKolka's answer and maybe help others save some time.
让我试着改进uKolka的答案,也许可以帮助其他人节省一些时间。
Use Numeral.js.
使用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>
You should go with Number.prototype.toLocaleString() only if its browser compatibilty is not an issue.
只有当它的浏览器兼容并不是问题时,才应该使用Number.prototype.toLocaleString()。
#18
5
For me, the best answer is using toLocaleString like some members said. If you want to include the '$' symbol just add languaje and type options. Here is and example to format a number to Mexican Pesos
对我来说,最好的答案是像一些成员说的那样使用toLocaleString。如果要包含“$”符号,只需添加语言和类型选项。这里是将数字格式化为墨西哥比索的例子
var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))
shortcut
快捷方式
1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})
#19
4
I think this function will take care of all the issues related to this problem.
我认为这个函数将处理与这个问题相关的所有问题。
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;
}
#20
3
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(".");
}
#21
2
I think your solution is one of the shorter ones I've seen for this. I don't think there are any standard JavaScript functions to do this sort of thing, so you're probably on your own.
我认为你的解决方案是我见过的较短的方案之一。我不认为有任何标准的JavaScript函数可以做这种事情,所以您可能需要自己做。
I checked the CSS 3 specifications to see whether it's possible to do this in CSS, but unless you want every digit in its own <span>
, I don't think that's possible.
我检查了CSS 3规范,看看是否有可能在CSS中这样做,但是除非您希望每个数字都在自己的中,否则我认为这是不可能的。
I did find one project on Google Code that looked promising: flexible-js-formatting. I haven't used it, but it looks pretty flexible and has unit tests using JsUnit. The developer also has a lot of posts (though old) about this topic.
我发现谷歌代码中有一个项目看起来很有前途:灵活的js格式。我还没有使用它,但是它看起来非常灵活,并且有使用JsUnit的单元测试。开发人员也有很多关于这个主题的帖子(虽然老了)。
Be sure to consider international users: lots of nations use a space as the separator and use the comma for separating the decimal from the integral part of the number.
一定要考虑到国际用户:许多国家使用空格作为分隔符,并使用逗号将小数部分与整数部分分开。
#22
2
Lots of good answers already. Here's another, just for fun:
已经有很多好的答案了。这是另一个,只是为了好玩:
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 - 1
return num + (pos && !(pos % 3) ? "," : "") + acc;
}, "") + (p[1] ? "." + p[1] : "");
}
Some examples:
一些例子:
format(77.03453, 2); // "77.03"
format(78436589374); // "78,436,589,374"
format(784, 4); // "784.0000"
format(-123456); // "-123,456"
#23
2
Here's my try:
这是我的尝试:
EDIT: Added in decimals
编辑:在小数补充道
function splitMille(n, separator = ',') {
// Cast to string
let 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 numbers
decimals = num.replace(/^.*(\..*)$/, '$1')
}
// Remove decimals from the number string
num = 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 number
return `${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)
#24
1
I added tofixed to Aki143S's solution. This solution uses dots for thousands separators and comma for the precision.
我在Aki143S的解决方案中添加了tofixed。这个解决方案在数千个分隔符和逗号中使用点作为精度。
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('');
};
Examples;
的例子;
formatNumber(17347, 0) = 17.347
formatNumber(17347, 3) = 17.347,000
formatNumber(1234563.4545, 3) = 1.234.563,454
#25
1
The solution from @user1437663 is great.
@user1437663的解决方案很棒。
Who really understands the solution is being prepared to understand complex regular expressions.
真正理解解决方案的人是准备理解复杂的正则表达式。
A small improvement to make it more readable:
一个小的改进使它更可读:
function numberWithCommas(x) {
var parts = x.toString().split(".");
return parts[0].replace(/\B(?=(\d{3})+(?=$))/g, ",") + (parts[1] ? "." + parts[1] : "");
}
The pattern starts with \B to avoid use comma at the beginning of a word. Interestingly, the pattern is returned empty because \B does not advance the "cursor" (the same applies to $).
模式以\B开头,避免在单词的开头使用逗号。有趣的是,模式返回为空,因为\B不推进“游标”(同样适用于$)。
O \B is followed by a less known resources but is a powerful feature from Perl's regular expressions.
O \B后面跟着一个鲜为人知的资源,但它是Perl正则表达式的一个强大特性。
Pattern1 (? = (Pattern2) ).
The magic is that what is in parentheses (Pattern2) is a pattern that follows the previous pattern (Pattern1) but without advancing the cursor and also is not part of the pattern returned. It is a kind of future pattern. This is similar when someone looks forward but really doesn't walk!
其神奇之处在于,圆括号(Pattern2)中的模式遵循了前面的模式(Pattern1),但是没有向前移动光标,也不是返回模式的一部分。这是一种未来的模式。当一个人向前看却真的不走的时候,这是相似的!
In this case pattern2 is
在这种情况下,模式n2是
\d{3})+(?=$)
It means 3 digits (one or more times) followed by the end of the string ($)
它的意思是3位数字(一个或多个)后面跟着字符串的末尾($)
Finally, Replace method changes all occurrences of the pattern found (empty string) for comma. This only happens in cases where the remaining piece is a multiple of 3 digits (such cases where future cursor reach the end of the origin).
最后,Replace方法将更改为逗号找到的所有模式(空字符串)。这种情况只发生在剩余部分是3位数字的倍数的情况下(这种情况下,未来的游标到达原点的末端)。
#26
1
Here is good solution with less coding...
这里有一个好的解决方案,少编码……
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 += ",";
}
#27
1
An alternative way, supporting decimals, different separators and negatives.
另一种方法,支持小数,不同的分隔符和负号。
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.abs(Math.ceil(number)).toString()
, i = n.length % 3
, f = n.substr(0, i)
;
if(number < 0) f = '-' + f;
for(;i<n.length;i+=3) {
if(i!=0) f+=ts;
f+=n.substr(i,3);
}
if(dp > 0)
f += ds + number.toFixed(dp).split('.')[1]
return f;
}
#28
1
I've adapted your code to work in TextBox (Input type="text") so we can enter and delete digits in real time without losing cursor. It's works also if you select range when you delete. And you can use arrows and home/end buttons freely.
Thanks for saving my time!
我修改了您的代码,使其在文本框(Input type="text")中工作,这样我们就可以在不丢失光标的情况下实时输入和删除数字。如果你在删除的时候选择range,它也可以工作。你可以*地使用箭头和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-keys
var selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positions
var 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 button
var delPos = parts[0].search(/\d{4}/);
if (delPos != -1) {//if found 4 digits in a row (',' is deleted)
if (e.keyCode == 8) {//if backspace flag
parts[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.443216
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digits
if (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;
}
To use this just added two events - onKeyUp and onKeyDown
要使用它,只需添加两个事件——onKeyUp和onKeyDown
<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>
#29
1
I thought I'd share a little trick which I'm using for large number formatting. Instead of inserting commas or spaces, I insert an empty but visible span in between the "thousands". This makes thousands easily visible, but it allows to copy/paste the input in the original format, without commas/spaces.
我想分享一个小技巧,我用它来进行大量的格式化。我没有插入逗号或空格,而是在“千”之间插入一个空但可见的跨度。这使得数以千计的输入很容易可见,但是它允许以原始格式复制/粘贴输入,而不需要逗号/空格。
// 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 present
var period = orgVal.indexOf(".");
var frac = period >= 0 ? orgVal.substr(period) : "";
// Work on input as an integer
var 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 information
res += frac;
return res;
}
With this CSS:
这个CSS:
.thousandsSeparator {
display : inline;
padding-left : 4px;
}
See an example JSFiddle.
看到一个JSFiddle例子。
#30
1
After not finding a modern and comprehensive solution here, I have written an arrow function (without regex) to solve the formatting problem and it allows the caller to provide number of fraction digits as well as the period and thousand separator for Europe and rest of the world.
在这里没有找到一个现代的、全面的解决方案之后,我编写了一个箭头函数(没有regex)来解决格式问题,它允许调用者为欧洲和世界其他地区提供小数位数、周期和千分隔符。
Examples:
例子:
numberFormatter(1234567890.123456) => 1,234,567,890 numberFormatter(1234567890.123456, 4) => 1,234,567,890.1235 numberFormatter(1234567890.123456, 4, '.', ',') => 1.234.567.890,1235 Europe
Here is the function written in ES6 (modern syntax):
下面是用ES6(现代语法)编写的函数:
const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => {
if (number!==0 && !number || !Number.isFinite(number)) return number
const frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0
const 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] : ''}`
}
It has been tested for negative, bad input and NaN cases. If the input is NaN then it simply returns it.
已检测为阴性、不良输入和NaN病例。如果输入是NaN,那么它只返回它。