正则表达式用逗号分隔数千并保留两位小数

我最近在回答另一个StackOverflow问题时想出了这段代码。 基本上,在模糊时,这段代码将正确地用逗号分隔数千,并将小数保留为两位数(如美元的编写方式[7,745.56])。

我想知道是否有更简洁的方法使用正则表达式 ,分离和切断过多的小数位。 我最近用我最近的尝试更新了这篇文章。 使用正则表达式有更好的方法吗?

输入 – >目标输出

7456 -> 7,456 45345 -> 45,345 25.23523534 -> 25.23 3333.239 -> 3,333.23 234.99 -> 234.99 2300.99 -> 2,300.99 23123123123.22 -> 23,123,123,123.22 

目前正则表达

 var result; var str = [] reg = new RegExp(/(\d*(\d{2}\.)|\d{1,3})/, "gi"); reversed = "9515321312.2323432".split("").reverse().join("") while (result = reg.exec(reversed)) { str.push(result[2] ? result[2] : result[0]) } console.log(str.join(",").split("").reverse().join("").replace(",.",".")) 

如果你真的坚持在纯正的正则表达式中做这个(并且截断而不是舍入小数位),我能想到的唯一解决方案是使用替换函数作为.replace()的第二个参数:

 ('' + num).replace( /(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g, function(m, s1, s2){ return s2 || (s1 + ','); } ); 

这使您的所有测试用例都通过:

 function format(num){ return ('' + num).replace( /(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g, function(m, s1, s2){ return s2 || (s1 + ','); } ); } test(7456, "7,456"); test(45345, "45,345"); test(25.23523534, "25.23"); //truncated, not rounded test(3333.239, "3,333.23"); //truncated, not rounded test(234.99, "234.99"); test(2300.99, "2,300.99"); test(23123123123.22, "23,123,123,123.22"); function test(num, expected){ var actual = format(num); console.log(num + ' -> ' + expected + ' => ' + actual + ': ' + (actual === expected ? 'passed' : 'failed') ); } 

作为Regex的替代方案,您可以使用以下方法

 Number(num.toFixed(2)).toLocaleString('en-US') 

要么

 num.toLocaleString('en-US', {maximumFractionDigits: 2}) 

你仍然会有toFixed(2) ,但它很干净。 toFixed(2)虽然不会像你想要的那样落地。 与{maximumFractionDigits: 2}相同,也是toLocaleString的第二个参数。

 var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22] for (var num of nums) console.log(num, '->', Number(num.toFixed(2)).toLocaleString('en-US') ) 

我添加了另一个图层,其中正则表达式在您的正则表达式逗号添加逻辑的基础上将不需要的小数点数降低到百分之一以下;

 val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,") 
 doIt("7456"); doIt("45345"); doIt("25.23523534"); doIt("3333.239"); doIt("234.99"); doIt("2300.99"); doIt("23123123123.22"); doIt("5812090285.2817481974897"); function doIt(val) { console.log(val + " -> " + val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,")); } 

RegEx再次营救!

我的解决方案有两个部分:

.toFixed :用于限制小数限制

/(\d)(?=(\d\d\d)+(?!\d))/g :它一次使用三位数的后向引用

以下是一切:

 // .toFixed((/\./g.test(num)) ? 2 : 0) it tests if the input number has any decimal places, if so limits it to 2 digits and if not, get's rid of it altogether by setting it to 0 num.toFixed((/\./g.test(num)) ? 2 : 0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")) 

你可以在这里看到它:

 var input = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22] input.forEach(function(num) { $('div') .append( $('

').text(num + ' => ' + num.toFixed( (/\./g.test(num))?2:0 ).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")) ); });

  

尝试:

 var n = 5812090285.2817481974897; n = n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); console.log(n); 

输出:

 5,812,090,285.28 

注意: .toFixed(2)返回一个string 。 因此,为了进一步简化这一点,您必须添加一种方法,在执行正则表达式之前将n转换为string 。 例如:

 n.toString.replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); //ofc with the additional regex 

虽然你会认为它在javascript中无关紧要,但显然在这种情况下确实如此。 所以我不知道不使用它会“少”多乱。

这是一种没有正则表达式的方法:

 value.toLocaleString("en-US", { maximumFractionDigits: 2 }) 
 function formatValue() { var source = document.getElementById("source"); var output = document.getElementById("output"); var value = parseFloat(source.value); output.innerText = value.toLocaleString("en-US", { maximumFractionDigits: 2 }); } 
   

style设置为"decimal" Intl.NumberFormat和第二个参数传递的options对象的Intl.NumberFormat设置为2

 const nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]; const formatOptions = {style:"decimal", maximumFractionDigits:2}; const formatter = new Intl.NumberFormat("en-US", formatOptions); const formatNums = num => formatter.format(num); let formattedNums = nums.map(formatNums); console.log(formattedNums); 

你可以这样做

 (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","") 

这里只是将数字转换为格式化数字,向下舍入到2位小数,然后删除.00(如果存在)。

这可以是您可以使用的一种方法。

 var format = function (num) { return (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","") } $(function () { $("#principalAmtOut").blur(function (e) { $(this).val(format($(this).val())); }); }); 
   

我在没有使用toFixed的情况下找到了基于toFixed答案的解决方案:

 function format(n) { n = +n; var d = Math.round(n * 100) % 100; return (Math.floor(n) + '').replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (d > 9 ? '.' + d : d > 0 ? '.0' + d : ''); } console.log(format(7456)); console.log(format(7456.0)); console.log(format(7456.1)); console.log(format(7456.01)); console.log(format(7456.001)); console.log(format(45345)); console.log(format(25.23523534)); console.log(format(3333.239)); console.log(format(234.99)); console.log(format(2300.99)); console.log(format(23123123123.22)); console.log(format('23123123123.22'));