如何在JavaScript中使用逗号作为千位分隔符来打印数字
我正在尝试用逗号作为千位分隔符在JavaScript中打印整数。 例如,我想显示编号1234567为“1,234,567”。 我怎么去做这个?
这是我如何做到这一点:
function numberWithCommas(x) { x = x.toString(); var pattern = /(-?\d+)(\d{3})/; while (pattern.test(x)) x = x.replace(pattern, "$1,$2"); return x; }
有一个更简单或更优雅的方式来做到这一点? 这将是很好,如果它也适用于浮动,但这不是必要的。 它不需要特定于语言环境来决定句点和逗号。
我从克里的答案中使用了这个想法,但简化了它,因为我只是为了特定的目的寻找一些简单的东西。 这是我做的:
function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }
这是你真正需要知道的。
@Neils Bom询问正则expression式是如何工作的。 我的解释有点长。 它不适合的评论,我不知道还有什么地方,所以我在这里做。 如果有人有任何其他build议,请告诉我。
正则expression式使用2个前瞻断言:一个正面的查找string中的任意一点,后面有一个3位数的倍数,否定断言确保该点只有3位数的整数倍。 replaceexpression式在那里放一个逗号。
例如,如果通过“123456789.01”,肯定断言将匹配7的左侧的每个点(因为“789”是3位数的倍数,“678”是3位数的倍数,“567”等等。)。 否定断言检查3位数的倍数之后没有任何数字。 “789”之后有一段时间,所以它恰好是3位数的倍数,所以逗号在那里。 “678”是3位数的倍数,但它后面有一个“9”,所以这3位数字是一组4的一部分,逗号不会到那里。 类似的“567”。 “456789”是6位数字,是3的倍数,所以前面有一个逗号。 “345678”是3的倍数,但它之后有一个“9”,所以没有逗号。 等等。 “\ B”使得正则expression式不会在string的开头加一个逗号。
@ neu-rah提到,如果在小数点后面有3位以上的数字,这个函数会在不需要的地方添加逗号。 如果这是一个问题,你可以使用这个function:
function numberWithCommas(x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); return parts.join("."); }
我很惊讶没有提到Number.prototype.toLocaleString 。 它是在JavaScript 1.5(1999年推出的)中实现的,因此它主要支持主stream浏览器。
var n = 34523453.345 n.toLocaleString() "34,523,453.345"
它也可以在v0.12中通过包含Intl在Node.js中工作
如果你想要不同的东西, Numeral.js可能会很有趣。
var number = 1234567890; // Example number to be converted
⚠请注意,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不支持):
var nf = new Intl.NumberFormat(); nf.format(number); // "1,234,567,890"
从我所检查的(Firefox至less)来看,它们在性能上都差不多。
我build议使用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); }
更新02/13/14
人们一直在报道这不能按预期工作,所以我做了一个包括自动化testing的JS小提琴 。
这是@ mikez302的答案的变体,但修改为支持小数(per @ neu-rah的反馈,numberWithCommas(12345.6789) – >“12,345.6,789”而不是“12,345.6789”
function numberWithCommas(n) { var parts=n.toString().split("."); return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : ""); }
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
感谢大家的回复。 我已经build立了一些答案,以制定更“一刀切”的解决scheme。
第一个片段增加了一个模拟PHP的number_format()
到Number原型的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); }
你可以使用这个如下:
var foo = 5000; console.log(foo.numberFormat(2)); // us format: 5,000.00 console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00
我发现我经常需要返回math运算的数字,但parseFloat将5,000转换为5,只需要第一个整数值序列。 所以我创build了自己的float转换函数,并将其添加到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.00 var fooFloat = fooString.getFloat(); // The number 5000; console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00
Number.prototype.toLocaleString()
如果它是由所有浏览器(Safari)本地提供的,将会非常棒。
我检查了所有其他的答案,但似乎没有人填补它。 这是一个朝着这个目标的实践,实际上是前两个答案的组合。 如果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));
我认为这是最短的正则expression式:
/\B(?=(\d{3})+\b)/g "123456".replace(/\B(?=(\d{3})+\b)/g, ",")
我检查了几个数字,它的工作。
如果您正在处理货币值和格式化,那么可能需要添加小型的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
可以使用浏览器的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似乎没有实现的时间表。
下面的代码使用char扫描,所以没有正则expression式。
function commafy( num){ var parts = (''+(num<0?-num:num)).split("."), s=parts[0], L, i=L= s.length, o=''; while(i--){ o = (i===0?'':((Li)%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/
我在写这篇文章之前写了这篇文章。 没有正则expression式,你可以真正理解代码。
$(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>
这是一个插入逗号分隔符的简单函数。 它使用数组函数而不是RegEx。
/** * Format a number as a string with commas separating the thousands. * @param num - The number to be formatted (eg 10000) * @return A string representing the formatted number (eg "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(''); };
让我试着改进uKolka的答案 ,也许可以帮助别人节省一些时间。
使用Numeral.js 。
document.body.textContent = numeral(1234567).format('0,0');
<script src="ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>
对于我来说,最好的答案就是像一些成员所说的那样使用toLocaleString。 如果你想包含'$'符号,只需添加语言和types选项。 这里是一个例子格式化一个数字墨西哥比索
var n = 1234567.22 alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))
我觉得这个function会处理所有与这个问题有关的问题。
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; }
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("."); }
Intl.NumberFormat
支持所有网页浏览器。
var number = 3500; console.log(new Intl.NumberFormat().format(number)); // → '3,500' if in US English locale
这是我的尝试:
编辑:添加小数
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)
我认为你的解决scheme是我见过的较短的解决scheme之一。 我不认为有任何标准的JavaScript函数来做这种事情,所以你可能是你自己的。
我检查了CSS3的规范,看看是否可以在CSS中做到这一点,但除非你想每个数字在自己的<span>
,否则我不认为这是可能的。
我确实在Google Code上find了一个看起来很有前景的项目: flexible-js-formatting 。 我没有使用它,但它看起来非常灵活,并使用JsUnit进行unit testing。 开发者也有很多关于这个话题的post(虽然很老)。
一定要考虑国际用户:许多国家使用空格作为分隔符,并使用逗号分隔数字整数部分的小数。
已经有很多好的答案了。 这是另一个,只是为了好玩:
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] : ""); }
一些例子:
format(77.03453, 2); // "77.03" format(78436589374); // "78,436,589,374" format(784, 4); // "784.0000" format(-123456); // "-123,456"
我join了Aki143S的解决scheme。 该解决scheme使用千位分隔符和逗号作为精度的点。
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.347 formatNumber(17347, 3) = 17.347,000 formatNumber(1234563.4545, 3) = 1.234.563,454
来自@ user1437663的解决scheme非常棒。
谁真正理解这个解决scheme正在准备理解复杂的正则expression式。
一个小的改进,使其更具可读性:
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正则expression式的一个强大function。
Pattern1 (? = (Pattern2) ).
神奇的是,括号( Pattern2 )中的内容是一个遵循先前模式( Pattern1 )的模式,但是不会推进游标,也不是返回模式的一部分。 这是一种未来的模式。 当有人向前看,但真的不走路,这是相似的!
在这种情况下, pattern2是
\d{3})+(?=$)
这意味着3位数字(一次或多次),后面跟着string($)的结尾
最后, Replace方法更改所有发现的模式(空string)的逗号。 这只发生在剩余片段是3位数的倍数的情况下(这种情况下,未来的光标到达原点的末端)。
另一种方式,支持小数,不同的分隔符和底片。
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; }
我已经调整了您的代码在TextBox(Input type =“text”)中工作,所以我们可以实时input和删除数字而不会丢失光标。 如果您在删除时select范围,也是有效的。 你可以自由地使用箭头和家庭/结束button。
感谢您节省我的时间!
//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
<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>
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:
.thousandsSeparator { display : inline; padding-left : 4px; }
See an example JSFiddle.
Here is a one line function with int & decimal support. I left some code in to convert the number to a string as well.
function numberWithCommas(x) { return (x=x+'').replace(new RegExp('\\B(?=(\\d{3})+'+(~x.indexOf('.')?'\\.':'$')+')','g'),','); }
For Integers I used a very simple method:
var myNumber = 99999, myString = myNumber + ""; myString.length > 3 ? return myString.substring(0, myString.length - 3) + "," + myString.substring(myString.length - 3) : return myString;
Yet another..(for int's as the question asks)
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(""); }