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

我是这样做的:

函数编号WithCommas(x){x=x.toString();var模式=/(-?\d+)(\d{3})/;while(模式测试(x))x=x.replace(模式,“$1,$2”);返回x;}console.log(数字与逗号(1000))

有没有更简单或更优雅的方法?如果它也可以与浮点运算一起使用,那就很好了,但这不是必须的。它不需要特定于区域设置来决定句点和逗号。


当前回答

我在早些时候找到了这个答案,我更新了它以允许负数。

您可以在将数字转换为字符串后使用它。

删除额外的小数位数只是为了方便,因为这是一种非常常见的情况。如果不需要,可以跳过它。

// Keep only digits, hyphen  and decimal points:
             myNum.toString()   .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, ",")

其他回答

@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) ).

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

在这种情况下,模式2是

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

它表示3位数字(一次或多次),后跟字符串结尾($)

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

如果所有浏览器(Safari)都提供Number.protype.toLocaleString(),那么它将非常棒。

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

var putThousandsSeparators;putThousandsSeparators=函数(值,sep){如果(sep==null){sep=',';}//检查是否需要格式化if(value.toString()==value.toLocaleString()){//分裂小数var parts=value.toString().split('.')//格式化整数parts[0]=parts[0]。替换(/\B(?=(\d{3})+(?!\d))/g,sep);//把它们放回一起值=部件[1]?parts.join('.'):parts[0];}其他{value=value.toLocaleString();}返回值;};警报(putThousandsSeparators(1234567.890));

我使用了克里的答案中的想法,但简化了它,因为我只是在为我的特定目的寻找简单的东西。以下是我所拥有的:

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

函数编号WithCommas(x){return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g,“,”);}功能测试(x,预期){常量结果=带逗号的数字(x);常量pass=result==预期;console.log(`${pass?”✓“:”错误===>“}${x}=>${result}`);回传;}让失败=0;失败+=!测试(0,“0”);失败+=!测试(100,“100”);失败+=!测试(1000,“1000”);失败+=!测试(10000,“10000”);失败+=!测试(100000,“100000”);失败+=!测试(1000000,“1000000”);失败+=!测试(10000000,“10000000”);if(失败){console.log(“${failures}测试失败”);}其他{console.log(“所有测试均通过”);}.作为控制台包装{最大高度:100%!重要的}


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

一个正数用于查找字符串中其后一行中具有3位数倍数的任何点,一个否定断言,以确保该点只有3位数的倍数。替换表达式在此处放置逗号。

例如,如果您传递它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提到,如果小数点后有超过3位数字,则该函数会在不需要的地方添加逗号。如果这是一个问题,您可以使用此函数:

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

函数编号WithCommas(x){var parts=x.toString().split(“.”);parts[0]=parts[0]。替换(/\B(?=(\d{3})+(?!\d))/g,“,”);return parts.join(“.”);}功能测试(x,预期){常量结果=带逗号的数字(x);常量pass=result==预期;console.log(`${pass?”✓“:”错误===>“}${x}=>${result}`);回传;}让失败=0;失败+=!测试(0,“0”);失败+=!测试(0.123456,“0.123456”);失败+=!测试(100,“100”);失败+=!测试(100.123456,“100.123456”);失败+=!测试(1000,“1000”);失败+=!测试(1000-123456,“1000-123456”);失败+=!测试(10000,“10000”);失败+=!测试(10000.123456,“10000.123454”);失败+=!测试(100000,“100000”);失败+=!测试(100000.123456,“10000.123456”);失败+=!测试(1000000,“1000000”);失败+=!测试(1000000123456,“1000000123446”);失败+=!测试(10000000,“10000000”);失败+=!测试(10000000.123456,“10000000.123454”);if(失败){console.log(“${failures}测试失败”);}其他{console.log(“所有测试均通过”);}.作为控制台包装{最大高度:100%!重要的}

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

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

函数编号WithCommas(x){return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g,“,”);}功能测试(x,预期){常量结果=带逗号的数字(x);常量pass=result==预期;console.log(`${pass?”✓“:”错误===>“}${x}=>${result}`);回传;}让失败=0;失败+=!测试(0,“0”);失败+=!测试(0.123456,“0.123456”);失败+=!测试(100,“100”);失败+=!测试(100.123456,“100.123456”);失败+=!测试(1000,“1000”);失败+=!测试(1000-123456,“1000-123456”);失败+=!测试(10000,“10000”);失败+=!测试(10000.123456,“10000.123454”);失败+=!测试(100000,“100000”);失败+=!测试(100000.123456,“10000.123456”);失败+=!测试(1000000,“1000000”);失败+=!测试(1000000123456,“1000000123446”);失败+=!测试(10000000,“10000000”);失败+=!测试(10000000.123456,“10000000.123454”);if(失败){console.log(“${failures}测试失败”);}其他{console.log(“所有测试均通过”);}.作为控制台包装{最大高度:100%!重要的}

(?<!\.\d*)是一个表示匹配前面不能有。后跟零个或多个数字。至少在V8中,反向查找比拆分和连接解决方案(比较)更快。

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

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

使用此CSS:

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

请参见示例JSFiddle。

使用正则表达式

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

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

使用toLocaleString()

var number = 123456.789;

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

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

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

ref MDN:Number.protype.toLocaleString()

使用国际号码格式()

var number = 123456.789;

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

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

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

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

参考Intl.NumberFormat

在这里演示<script type=“text/javascript”>//使用正则表达式函数到逗号(值){return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g,“,”);}函数命令(){var num1=文档.myform.number1.value;//使用正则表达式document.getElementById('result1').value=toCommas(parseInt(num1));//使用toLocaleString()document.getElementById('result2').value=parseInt(num1).toLocaleString('ja-JP'{style:'货币',货币:'日元'});//使用国际号码格式()document.getElementById('result3').value=新Intl.NumberFormat('ja-JP'{style:'货币',货币:'日元'}).格式(num1);}</script><FORM NAME=“myform”><INPUT TYPE=“text”NAME=“number1”VALUE=“123456789”><br><INPUT TYPE=“button”NAME=“button“Value=”=>“onClick=”commas()“><br>使用正则表达式<br><INPUT TYPE=“text”ID=“result1”NAME=“result1”VALUE=“”><br>使用toLocaleString()<br><INPUT TYPE=“text”ID=“result2”NAME=“result2“VALUE=”“><br>使用国际号码格式()<br><INPUT TYPE=“text”ID=“result3”NAME=“result3“VALUE=”“></FORM>表演http://jsben.ch/sifRd