Cách in một số bằng dấu phẩy dưới dạng hàng ngàn dấu phân cách trong JavaScript


1781

Tôi đang cố gắng in một số nguyên trong JavaScript bằng dấu phẩy dưới dạng hàng nghìn dấu phân cách. Ví dụ: tôi muốn hiển thị số 1234567 là "1,234,567". Tôi sẽ đi đâu để tới đó?

Đây là cách tôi đang làm:

function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

Có một cách đơn giản hơn hoặc thanh lịch hơn để làm điều đó? Sẽ thật tuyệt nếu nó cũng hoạt động với phao, nhưng điều đó là không cần thiết. Không cần phải là địa phương cụ thể để quyết định giữa các dấu chấm và dấu phẩy.


156
Số (x) .toLocaleString ()
Boffin

@Boffin điều này không hoạt động đối với số loại đầu vào (vì dấu phẩy) - trong câu trả lời được chấp nhận, chúng tôi có thể thay thế dấu phẩy thành dấu chấm và số loại đầu vào sẽ hoạt động
Vitaly Zdanevich

48
Đáng chú ý là Number.prototype.toLocaleString vẫn không hoạt động trong Safari, vào năm 2016 . Thay vì thực sự định dạng số, nó chỉ trả về nó, không có lỗi ném. Có khuôn mặt lớn nhất hiện nay là kết quả của điều đó ... #goodworkApple
ký vào

Tuy nhiên, nó dường như hoạt động trong safari iOS.
Tim

toLocaleString không nhất quán và không nên được sử dụng. Ví dụ: trên Firefox, điều này sẽ trả về 1,234 nhưng trên IE, điều này sẽ thêm số thập phân: 1,234,00
Bort

Câu trả lời:


2834

Tôi đã sử dụng ý tưởng từ câu trả lời của Kerry, nhưng đơn giản hóa nó vì tôi chỉ tìm kiếm thứ gì đó đơn giản cho mục đích cụ thể của mình. Đây là những gì tôi đã làm:

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


Regex sử dụng 2 xác nhận lookahead:

  • một số dương để tìm bất kỳ điểm nào trong chuỗi có bội số gồm 3 chữ số liên tiếp sau nó,
  • một xác nhận phủ định để đảm bảo rằng điểm đó chỉ có chính xác bội số của 3 chữ số. Biểu thức thay thế đặt dấu phẩy ở đó.

Ví dụ: nếu bạn vượt qua nó 123456789.01, xác nhận tích cực sẽ khớp mọi điểm ở bên trái của 7 (vì 789là bội của 3 chữ số, 678là bội của 3 chữ số 567, v.v.). Xác nhận phủ định kiểm tra rằng bội số của 3 chữ số không có bất kỳ chữ số nào sau nó. 789có một khoảng thời gian sau nó vì vậy nó chính xác là bội của 3 chữ số, vì vậy dấu phẩy xuất hiện ở đó. 678là bội của 3 chữ số nhưng nó có một9 sau, vì vậy 3 chữ số đó là một phần của một nhóm 4 và dấu phẩy không xuất hiện ở đó. Tương tự cho 567. 456789là 6 chữ số, là bội của 3, vì vậy dấu phẩy đi trước đó. 345678là bội số của 3, nhưng nó có 9sau nó, vì vậy không có dấu phẩy nào ở đó. Và như thế. Các\B giữ cho regex không đặt dấu phẩy ở đầu chuỗi.

@ neu-rah đã đề cập rằng hàm này thêm dấu phẩy ở những vị trí không mong muốn nếu có nhiều hơn 3 chữ số sau dấu thập phân. Nếu đây là một vấn đề, bạn có thể sử dụng chức năng này:

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

@ tjcrowder chỉ ra rằng bây giờ JavaScript có lookbehind ( thông tin hỗ trợ ), nó có thể được giải quyết trong chính biểu thức chính quy:

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

(?<!\.\d*)là một cái nhìn tiêu cực nói rằng trận đấu không thể được bắt đầu bằng một số .theo sau bằng 0 hoặc nhiều chữ số. Giao diện tiêu cực nhanh hơn so với splitjoingiải pháp ( so sánh ), ít nhất là trong V8.


21
Rất tuyệt, đã nhận thấy rằng nó có vấn đề với các số có nhiều hơn 3 vị trí sau dấu thập phân.
Eric Petroelje

60
thử sốWithCommas (12345.6789) -> "12.345.6.789" tôi không thích nó
neu-rah

4
Nó không hoạt động tốt với các phân số, chúng tôi sẽ không muốn có dấu phẩy sau dấu thập phân
Mugen

30
Cải thiện nhỏ mà sửa chữa sau '.' vấn đề '123456789.01234'.replace (/ \ B (? = (? = \ d * \.) (\ d {3}) + (?! \ d)) / g,' _ ')
Dmitrij Golubev

8
@DmitrijGolubev Không hoạt động cho số nguyên. Có lẽ buộc dấu thập phân sẽ là giải pháp.
Vlad

1809

Tôi ngạc nhiên không ai nhắc đến Number.prototype.toLocaleString . Nó được triển khai trong JavaScript 1.5 (được giới thiệu vào năm 1999) vì vậy về cơ bản nó được hỗ trợ trên tất cả các trình duyệt chính.

var n = 34523453.345
n.toLocaleString()
"34,523,453.345"

Nó cũng hoạt động trong Node.js kể từ v0.12 thông qua việc bao gồm Intl

Chỉ cần chú ý rằng hàm này trả về một chuỗi, không phải là một số.

Nếu bạn muốn một cái gì đó khác biệt, Numeral.js có thể thú vị.


17
@csigrist Điểm tốt, nhưng nó không tệ như nó có vẻ. Tốc độ phụ thuộc vào trình duyệt. Trong FF hoặc Opera, nó hoạt động tốt. Tôi hút trong Chrome mặc dù. Đối với số không: var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00"Các tùy chọn đó không hoạt động trong FF hoặc Safari.
uKolka

22
Sự khác biệt hiệu suất có thể hoặc không thể là một vấn đề, tùy thuộc vào bối cảnh. Nếu được sử dụng cho một bảng khổng lồ 1000 kết quả thì nó sẽ quan trọng hơn nhưng nếu chỉ được sử dụng cho một giá trị duy nhất, sự khác biệt là không đáng kể. Nhưng lợi thế là nó nhận biết được địa phương, vì vậy một người nào đó ở châu Âu sẽ thấy 34.523.453.345 hoặc 34 523 453.345 . Điều này sẽ quan trọng hơn trên một trang web có khách truy cập từ nhiều quốc gia.
T Nguyễn

6
Tuyệt vời. Cuối cùng là một câu trả lời với chức năng bản địa. Và hơn thế nữa, cái này hiển thị đúng ở các quốc gia khác nhau với các dải phân cách khác nhau (ở Cộng hòa Séc chúng tôi viết X XXX XXX,YYY).
Tomáš Zato - Tái lập lại

22
Cập nhật cho nhân viên Google: toLocaleStringhoạt động trong Node.js kể từ v0.12 thông qua việc bao gồm Intl .
srobinson

8
@MSC bạn nên thử parseInt("1234567", 10).toLocaleString('en-US', {minimumFractionDigits: 2})hoặc new Number("1234567").toLocaleString('en-US', {minimumFractionDigits: 2})thay vào đó. Nó không hoạt động vì bạn sử dụng nó trên một chuỗi, không phải là một số.
uKolka

244
var number = 1234567890; // Example number to be converted

Lưu ý rằng javascript có giá trị nguyên tối đa9007199254740991


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 không được hỗ trợ):

var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"

Từ những gì tôi đã kiểm tra (ít nhất là Firefox), cả hai đều ít nhiều giống nhau về hiệu suất.


6
NumberFormat không được hỗ trợ trên Safari, cho bất kỳ ai đang triển khai ở đó.
marcovega

6
toLocaleString cũng không được hỗ trợ trên safari
Deepak Banka

3
Hỗ trợ trình duyệt luôn được đề cập ở cuối mỗi trang MDN mà tôi đã liên kết đến.
vsync

5
toLocaleStringcông việc cơ bản trên safari, tùy chọn không
dandavis

3
các toLocaleStringgiải pháp nên có lẽ cũng bao gồm các địa phương mong muốn, vì vậy toLocaleString("en"), vì người Anh sử dụng mẫu dấu phẩy. Tuy nhiên, nếu toLocaleString()không có chỉ báo miền địa phương được chạy ở Pháp, thì nó sẽ mang lại thời gian thay vì dấu phẩy vì đó là những gì được sử dụng để phân tách hàng ngàn cục bộ.
Mike 'Pomax' Kamermans

112

Tôi đề nghị sử dụng number_format () của phpjs.org

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

CẬP NHẬT ngày 13/2/14

Mọi người đã báo cáo việc này không hoạt động như mong đợi, vì vậy tôi đã thực hiện một Fiddle JS bao gồm các bài kiểm tra tự động.

Cập nhật ngày 26/11/2017

Đây là một đoạn trích với Stack Snippet với đầu ra được sửa đổi một chút:

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


Không phải tôi đánh dấu nó xuống, nhưng tôi tin rằng mọi người đã làm như vậy bởi vì nó không hoạt động. Khi tôi đứng, tôi thấy ngay cả một số bài kiểm tra của bạn không hoạt động.
Andrew S

3
@Andrew S - Chỉ có 1 người đã đánh dấu nó xuống. Nó hoạt động, tôi đã sử dụng nó trong mã của riêng tôi nhiều lần. Đó cũng không phải là mã của tôi (cũng không phải thử nghiệm của tôi), tôi đã tham khảo trang web mà nó đến từ đây, một trang web nổi tiếng. Có lẽ họ có phiên bản cập nhật của nó) vì mã bạn đang xem là 3 tuổi.
Kerry Jones

13
@ernix - Toán tử yêu cầu JavaScript, câu trả lời tôi đưa ra JavaScript. Đây là một giải thích JavaScript của một chức năng PHP.
Kerry Jones

2
@ernix - nó hoạt động chính xác như mong đợi với ví dụ mà OP đưa ra. Tôi đặt một fiddle để bạn có thể nhìn thấy.
Kerry Jones

4
@ernix - Được rồi, nhưng vấn đề là nó thực hiện chính xác những gì OP yêu cầu. Nó là từ một trang web khác (không được tôi duy trì và tôi đã nói điều này trước đây) và khi đưa ra các biến thích hợp, nó hoạt động chính xác như đã nêu. Nếu bạn tin rằng đó là một lỗi, hãy liên hệ với phpjs.org hoặc xem họ có phiên bản cập nhật không.
Kerry Jones

75

Đây là một biến thể của câu trả lời của @ mikez302, nhưng được sửa đổi để hỗ trợ các số có số thập phân (phản hồi của mỗi @ neu-rah đó là sốWithCommas (12345.6789) -> "12.345.6.789" thay vì "12.345.6789"

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


67
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

Điều này làm gì mà câu trả lời của tôi không? Regex trông hơi khác nhau nhưng có vẻ như nó nên làm điều tương tự.
Elias Zamaria

8
nó ngắn hơn :)
Tutankhamen

4
Đây là thanh lịch. Chính xác những gì tôi đang tìm kiếm.
truyền thống

4
Từ blog.tompawlak.org/number-currency-formatted-javascript ? Vấn đề đã biết: formatNumber (0.123456) = 0.123.456 Sự vắng mặt của lookbehind trong JS gây khó khăn cho việc khắc phục nó bằng một biểu thức thanh lịch.
Vlad

1
123456789.123456789.toString (). Thay thế (/ (\ d) (? = (\ D {3}) + \.) / G, '$ 1,') => 123,456,789.12345679
kenber siêu

53

Sử dụng biểu thức chính quy

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

Sử dụng 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

tham chiếu MDN: Number.prototype.toLocaleString ()

Sử dụng Intl.NumberFormat ()

var number = 123456.789;

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

// the Japanese yen doesn't use a minor 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"

ref Intl.NumberFormat

DEMO TẠI ĐÂY

<script type="text/javascript">
  // Using Regular expression
  function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  }

  function commas() {
    var num1 = document.myform.number1.value;

    // Using Regular expression
    document.getElementById('result1').value = toCommas(parseInt(num1));
    // Using toLocaleString()

    document.getElementById('result2').value = parseInt(num1).toLocaleString('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    });

    // Using Intl.NumberFormat()
    document.getElementById('result3').value = new Intl.NumberFormat('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    }).format(num1);
  }
</script>
<FORM NAME="myform">
  <INPUT TYPE="text" NAME="number1" VALUE="123456789">
  <br>
  <INPUT TYPE="button" NAME="button" Value="=>" onClick="commas()">
  <br>Using Regular expression
  <br>
  <INPUT TYPE="text" ID="result1" NAME="result1" VALUE="">
  <br>Using toLocaleString()
  <br>
  <INPUT TYPE="text" ID="result2" NAME="result2" VALUE="">
  <br>Using Intl.NumberFormat()
  <br>
  <INPUT TYPE="text" ID="result3" NAME="result3" VALUE="">

</FORM>

Hiệu suất

Hiệu suất http://jsben.ch/sifRd


Điều này không hoạt động nếu bạn đang gõ động. Nếu bạn chỉ cung cấp cho nó một giá trị thì nó hoạt động, nhưng nếu bạn đang cung cấp một giá trị liên tục một cách linh hoạt thì dấu phẩy được thêm vào sai vị trí.
Edgar Quintero

Tôi đã cập nhật bản demo bên dưới câu trả lời của tôi. Khi nhập một giá trị động trong một hộp văn bản. bạn thử dùng thử @EdgarQuintero
Ngô Quang

39

Intl.NumberFormat

Hàm JS gốc. Được hỗ trợ bởi IE11, Edge, Safari mới nhất, Chrome, Firefox, Opera, Safari trên iOS và Chrome trên Android.

var number = 3500;

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

Câu trả lời của tôi đã được cập nhật để đáp ứng với ý kiến ​​của bạn. Cảm ơn!
Dustin Sun

35

Cảm ơn tất cả mọi người đã trả lời. Tôi đã xây dựng một số câu trả lời để đưa ra giải pháp "một cỡ vừa cho tất cả".

Đoạn mã đầu tiên thêm một chức năng bắt chước PHP của number_format()nguyên mẫu Số. Nếu tôi định dạng một số, tôi thường muốn các vị trí thập phân để hàm lấy số vị trí thập phân để hiển thị. Một số quốc gia sử dụng dấu phẩy làm số thập phân và số thập phân làm dấu phân cách hàng nghìn để chức năng cho phép các dấu phân cách này được đặt.

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

Bạn sẽ sử dụng điều này như sau:

var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

Tôi thấy rằng tôi thường cần lấy lại số cho các phép toán, nhưng parseFloat chuyển đổi 5.000 thành 5, chỉ cần lấy chuỗi giá trị nguyên đầu tiên. Vì vậy, tôi đã tạo ra hàm chuyển đổi float của riêng mình và thêm nó vào nguyên mẫu 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));
}

Bây giờ bạn có thể sử dụng cả hai chức năng như sau:

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

2
Rất hay, tôi đã mượn phương thức đầu tiên;) Nhưng nó không tạo ra kết quả chính xác khi bạn muốn sử dụng định dạng châu Âu và số này là phân số. Dòng 5 phải là:var parts = this.toFixed(decimals).toString().split('.');
vbwx

Bạn đúng rồi! toFixed () thay đổi dấu phẩy thành dấu chấm và vì vậy '.' nên được sử dụng thay vì var dec_point. Cảm ơn đã chỉ ra rằng.
Không có

bạn có thể làm một mô-đun npm cho việc này?
chovy

3
@ J.Money .toString là không cần thiết, toFixed đã trả về một chuỗi.
Ariel

Tôi không biết tại sao bạn lại đề cập đến PHP ở đây, hoặc đưa ra một chức năng bảo vệ đã tồn tại
vsync

27

Tôi khá ấn tượng bởi số lượng câu trả lời mà câu hỏi này có được. Tôi thích câu trả lời của uKolka :

n.toLocaleString()

Nhưng thật không may, ở một số địa phương như Tây Ban Nha, nó không hoạt động (IMHO) như mong đợi cho các số dưới 10.000:

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

Cho 1000và không1.000 .

Xem toLocaleString không hoạt động trên các số nhỏ hơn 10000 trong tất cả các trình duyệt để biết lý do.

Vì vậy, tôi đã phải sử dụng câu trả lời của Elias Zamaria để chọn đúng hàng ngàn ký tự phân cách:

n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Công cụ này hoạt động tốt như một lớp lót cho cả hai địa phương sử dụng ,hoặc .là dải phân cách hàng nghìn và bắt đầu hoạt động từ 1.000 trong mọi trường hợp.

Number(1000).toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Cung cấp 1.000với một bối cảnh địa phương Tây Ban Nha.

Nếu bạn muốn kiểm soát tuyệt đối cách thức một số được định dạng, bạn cũng có thể thử các cách sau:

let number   = 1234.567
let decimals = 2
let decpoint = '.' // Or Number(0.1).toLocaleString().substring(1, 2)
let thousand = ',' // Or Number(10000).toLocaleString().substring(2, 3)

let n = Math.abs(number).toFixed(decimals).split('.')
n[0] = n[0].split('').reverse().map((c, i, a) =>
  i > 0 && i < a.length && i % 3 == 0 ? c + thousand : c
).reverse().join('')
let final = (Math.sign(number) < 0 ? '-' : '') + n.join(decpoint)

console.log(final)

Cho 1,234.57.

Điều này không cần một biểu thức thông thường. Nó hoạt động bằng cách điều chỉnh số cho số thập phân mong muốn với số thập phân mong muốn toFixed, sau đó chia số đó xung quanh dấu thập phân .nếu có. Phía bên trái sau đó được biến thành một mảng các chữ số được đảo ngược. Sau đó, một dấu tách hàng ngàn được thêm vào mỗi ba chữ số từ đầu và kết quả lại đảo ngược. Kết quả cuối cùng là sự kết hợp của hai phần. Dấu của số đầu vào được loại bỏ bằngMath.abs đầu tiên và sau đó đặt lại nếu cần thiết.

Nó không phải là một lớp lót nhưng không dài hơn nhiều và dễ dàng biến thành một chức năng. Các biến đã được thêm vào cho rõ ràng, nhưng các biến có thể được thay thế bằng các giá trị mong muốn của chúng nếu biết trước. Bạn có thể sử dụng các biểu thức sử dụng toLocaleStringnhư một cách để tìm ra các ký tự phù hợp cho dấu thập phân và dấu phân cách hàng nghìn cho ngôn ngữ hiện tại (lưu ý rằng những ký tự đó yêu cầu Javascript hiện đại hơn.)


23

Tôi nghĩ rằng đây là biểu thức chính quy ngắn nhất thực hiện nó:

/\B(?=(\d{3})+\b)/g

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

Tôi đã kiểm tra nó trên một vài con số và nó hoạt động.


chỉ hoạt động tốt nếu bạn không có số float với hơn 3 số sau dấu phân cách trong trường hợp này là dấu chấm. Nếu không, nó cũng thêm dấu phẩy. "1234567890.1234567890" .replace (/ \ B (? = (\ D {3}) + \ b) / g, ",") Điều này sẽ không hoạt động chẳng hạn. Trả về "1,234,567,890,1,234,567,890"
Marcio

1
Hoạt động tốt cho tiền tệ mặc dù! Chỉ cần làm tròn các chữ số của bạn trước khi thêm dấu phẩy.
Kyle Chadha

1
Nó thêm, sau điểm thập phân: 12.3456 ".replace (/ \ B (? = (\ D {3}) + \ b) / g,", ") == 12.3,456
Shree Tiwari

21

Number.prototype.toLocaleString()sẽ thật tuyệt vời nếu nó được cung cấp nguyên bản bởi tất cả các trình duyệt (Safari) .

Tôi đã kiểm tra tất cả các câu trả lời khác nhưng dường như không ai trả lời được. Đây là một poc hướng tới đó, mà thực sự là sự kết hợp của hai câu trả lời đầu tiên; nếu toLocaleStringhoạt động nó sử dụng nó, nếu nó không sử dụng một chức năng tùy chỉnh.

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


1
Xin lưu ý rằng polyfill chỉ hoạt động với các số có nhiều nhất là 3 số thập phân. Ví dụ: 0.12345sẽ xuất ra 0.12,345. Một triển khai tốt cho việc này có thể được tìm thấy trong dấu gạch dưới. Chuỗi
Andy

bạn đã đúng, đặt một value > 1000điều kiện nếu điều kiện khắc phục trường hợp đó, tuy nhiên đây là một poc và tất nhiên các phiên bản thử nghiệm tốt hơn có thể được tìm thấy ở nơi khác, cảm ơn vì đã chỉ ra.
Sinan

1
Nó không đủ để đặt value > 1000, bởi vì nó sẽ giống nhau cho bất kỳ số nào và hơn 3 số thập phân. ví dụ 1000.12345trả về 1,000.12,345. Câu trả lời của bạn là tuyệt vời và đi đúng hướng, nhưng chỉ là không đầy đủ. Tôi chỉ cố gắng chỉ ra cho những người khác có thể vấp phải câu trả lời của bạn và chỉ sao chép / dán nó mà không kiểm tra với dữ liệu đầu vào khác nhau.
Andy

1
Được rồi, điều này cần một chỉnh sửa khác :) Tôi đồng ý, nhưng bây giờ ít nhất nó sẽ hoạt động cho hầu hết các trường hợp.
Sinan

18

Dấu phân cách hàng nghìn có thể được chèn theo cách thân thiện quốc tế bằng cách sử dụng Intlđối tượng của trình duyệt :

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

Xem bài viết của MDN trên NumberFormat để biết thêm, bạn có thể chỉ định hành vi ngôn ngữ hoặc mặc định cho người dùng. Đây là một chút ngu ngốc hơn bởi vì nó tôn trọng sự khác biệt địa phương; nhiều quốc gia sử dụng dấu chấm để phân tách các chữ số trong khi dấu phẩy biểu thị số thập phân.

Intl.NumberFormat chưa có sẵn trong tất cả các trình duyệt, nhưng nó hoạt động trong Chrome, Opera và IE mới nhất. Bản phát hành tiếp theo của Firefox sẽ hỗ trợ nó. Webkit dường như không có thời gian để thực hiện.


2
Mặc dù điều này sẽ rất tuyệt nếu chúng ta có thể sử dụng một chức năng tích hợp đơn giản, nó có trình duyệt thực hiện khủng khiếp. Ví dụ: IE 8-10 và tất cả Safari không hỗ trợ điều này
Blaine Kasten

@BlaineKasten có một polyfill tương thích hoàn toàn cho các trình duyệt cũ hơn có sẵn ở đây: github.com/andyearnshaw/Intl.js nó rất lớn, nhưng nó hoạt động.
Mahn

1
Có sẵn thông qua CDN pollyfill (chỉ trả về những gì cần thiết dựa trên useragent): cdn.polyfill.io/v2/polyfill.min.js?features=Intl
Kevin

Có vấn đề định dạng số lượng lớn với toLocaleString, điều này hoạt động rất tốt (với polyfill)
hỏi_io

18

Bạn có thể sử dụng thủ tục này để định dạng tiền tệ của bạn cần.

var nf = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’

Để biết thêm thông tin bạn có thể truy cập liên kết này.

https://www.justinmccandless.com/post/formatted-currency-in-javascript/


Đây là câu trả lời chính xác, di động, bản địa. Ước gì tôi có thể nâng cao hơn một lần.
Jared Smith

14

nếu bạn đang xử lý các giá trị tiền tệ và định dạng rất nhiều thì có thể đáng để thêm hạch toán kế toán nhỏ xử lý nhiều trường hợp cạnh và bản địa hóa:

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

1
Liên kết không hoạt động nữa. Nhưng trông tương tự như thế này: openexchangerates.github.io/accounting.js
ush189

13

Đoạn mã sau sử dụng quét char, do đó không có 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] : ''); 
}

Nó cho thấy hiệu suất đầy hứa hẹn: http://jsperf.com/number-formatted-with-commas/5

2015.4.26: Sửa lỗi nhỏ để giải quyết vấn đề khi num <0. Xem https://jsfiddle.net/runsun/p5tqqvs3/


điều này không hoạt động với commafy(-123456)nó mang lại-,123,456
wrossmck

Điều đó thật tuyệt! Cảm ơn bạn đã tập hợp jsperf
fregante

Đoạn trích này là một con quái vật tuyệt đối, thực hiện mọi thứ.
NiCk Newman

13

Đây là một chức năng đơn giản chèn dấu phẩy cho hàng nghìn dấu phân cách. Nó sử dụng các hàm mảng chứ không phải là 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('');
};

Liên kết CodeSandbox với các ví dụ: https://codesandbox.io/s/p38k63w0vq


1
Xin chào .. Ví dụ này là tuyệt vời. Nhưng nó cũng sẽ đặt dấu phẩy cho phần thập phân. chỉ cần chỉnh sửa: function formatNumber (num) {var binaryPart = ''; num = num.toString (); if (num.indexOf ('.')! = -1) {binaryPart = '.' + num.split ('.') [1]; num = parseInt (num.split ('.') [0]); } var mảng = num.toString (). split (''); chỉ số var = -3; while (mảng.length + index> 0) {mảng.splice (index, 0, ','); // Giảm 4 vì chúng ta vừa thêm một đơn vị khác vào mảng. chỉ số - = 4; } return mảng.join ('') + binaryPart; };
Aki143S

Cảm ơn ngài. Đây chính xác là những gì tôi cần.
Amir Hossein Ahmadi

11

Sử dụng mã này để xử lý định dạng tiền tệ cho Ấn Độ. Mã quốc gia có thể được thay đổi để xử lý tiền tệ quốc gia khác.

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

// Use it.

formatter.format(amount);

đầu ra:

3,50,256.95

Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời. Đọc này .
Chaieshwar Inde

@ShanteshwarInde tôi sẽ thêm bối cảnh bổ sung để cải thiện câu trả lời chắc chắn
Bathri Nathan

11

Bạn cũng có thể sử dụng hàm tạo Intl.NumberFormat . Đây là cách bạn có thể làm điều đó.

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

nút này không hoạt động js. Nó không đưa ra phản hồi ở định dạng Ấn Độ
Suraj Dalvi

7

Tôi đã viết bài này trước khi vấp ngã trên bài đăng này. Không có regex và bạn thực sự có thể hiểu mã.

$(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>


1
Tôi đã thêm s.toString () vào đầu hàm để nó cũng có thể chấp nhận số, không chỉ chuỗi. Đây là câu trả lời ưa thích của tôi vì nó có thể đọc được, súc tích và không có lỗi nào mà các câu trả lời regex dường như có.
FeFiFoFu

7
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(".");
}

EDIT: Hàm chỉ hoạt động với số dương. ví dụ:

var number = -123123231232;
formatNumber(number)

Đầu ra: "123,123,231,232"

Nhưng để trả lời câu hỏi trên toLocaleString()phương pháp chỉ giải quyết vấn đề.

var number = 123123231232;
    number.toLocaleString()

Đầu ra: "123,123,231,232"

Vui lên!


1
Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Vịt Donald

1
Kịch bản đẹp, nhưng nó không hoạt động với số âm.
Ralph David Abernathy

7

Câu trả lời của tôi là câu trả lời duy nhất thay thế hoàn toàn jQuery bằng một lựa chọn hợp lý hơn nhiều:

function $(dollarAmount)
{
    const locale = 'en-US';
    const options = { style: 'currency', currency: 'USD' };
    return Intl.NumberFormat(locale, options).format(dollarAmount);
}

Giải pháp này không chỉ thêm dấu phẩy mà còn làm tròn đến đồng xu gần nhất trong trường hợp bạn nhập số tiền như $(1000.9999)bạn sẽ nhận được $ 1,001,00. Ngoài ra, giá trị bạn nhập có thể là một số hoặc một chuỗi một cách an toàn; nó không thành vấn đề

Nếu bạn đang giao dịch với tiền, nhưng không muốn có ký hiệu đô la hàng đầu được hiển thị trên số tiền, bạn cũng có thể thêm chức năng này, sử dụng chức năng trước đó nhưng loại bỏ $:

function no$(dollarAmount)
{
    return $(dollarAmount).replace('$','');
}

Nếu bạn không giao dịch với tiền và có các yêu cầu định dạng thập phân khác nhau, thì đây là một chức năng linh hoạt hơn:

function addCommas(number, minDecimalPlaces = 0, maxDecimalPlaces = Math.max(3,minDecimalPlaces))
{
    const options = {};
    options.maximumFractionDigits = maxDecimalPlaces;
    options.minimumFractionDigits = minDecimalPlaces;
    return Intl.NumberFormat('en-US',options).format(number);
}

Ồ, và nhân tiện, việc mã này không hoạt động trong một số phiên bản Internet Explorer cũ là hoàn toàn có chủ ý. Tôi cố gắng phá vỡ IE bất cứ lúc nào tôi có thể bắt nó không hỗ trợ các tiêu chuẩn hiện đại.

Xin nhớ rằng lời khen quá mức, trong phần bình luận, được coi là lạc đề. Thay vào đó, chỉ cần tắm cho tôi với số phiếu tăng.


1
Số (n) .toLocaleString () có vẻ là câu trả lời hay nhất nhưng có lẽ bạn muốn sử dụng một cái gì đó giống như Intl.NumberFormat ('en-US'). Định dạng (n) thay vì tước bỏ các ký hiệu đô la và số thập phân nếu tất cả người dùng muốn là dấu phẩy trong số của họ.
bmacnaughton

@bmacnaughton: Đó là một điểm tốt khi bạn không giao dịch với tiền. Tuy nhiên, nếu bạn đang giao dịch với tiền và chỉ "không muốn ký hiệu đô la hàng đầu", Số (1000,50) .toLocaleString () tạo ra '1.000,5', loại bỏ số 0 không đáng kể thường được giữ khi hiển thị giá trị tiền. Nhận xét tốt: mọi người nên biết những gì bạn đã nói.
Lonnie hay nhất

6

Đối với tôi, câu trả lời tốt nhất là sử dụng toLocaleString như một số thành viên đã nói. Nếu bạn muốn bao gồm biểu tượng '$', chỉ cần thêm tùy chọn languaje và loại. Dưới đây là và ví dụ để định dạng một số sang peso Mexico

var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))

đường tắt

1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})

5

Hãy để tôi cố gắng cải thiện câu trả lời của uKolka và có thể giúp người khác tiết kiệm thời gian.

Sử dụng 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>

Bạn chỉ nên sử dụng Number.prototype.toLocaleString () nếu trình duyệt tương thích không phải là vấn đề.


điều này đã truyền cảm hứng cho tôi để cài đặt con số
npm

5

Một cách khác, hỗ trợ số thập phân, dấu phân cách và phủ định khác nhau.

var number_format = function(number, decimal_pos, decimal_sep, thousand_sep) {
    var ts      = ( thousand_sep == null ? ',' : thousand_sep )
        , ds    = ( decimal_sep  == null ? '.' : decimal_sep )
        , dp    = ( decimal_pos  == null ? 2   : decimal_pos )

        , n     = Math.floor(Math.abs(number)).toString()

        , i     = n.length % 3 
        , f     = ((number < 0) ? '-' : '') + n.substr(0, i)
    ;

    for(;i<n.length;i+=3) {
        if(i!=0) f+=ts;
        f+=n.substr(i,3);
    }

    if(dp > 0) 
        f += ds + parseFloat(number).toFixed(dp).split('.')[1]

    return f;
}

Một số chỉnh sửa của @Jignesh Sanghani, đừng quên nêu lên nhận xét của anh ấy.


Hoàn hảo cho tôi, chỉ cần thêm một dòng mới để xóa định dạng trước khi xử lý.
Dennis Heiden

2
fn.substr(0, i)thay thế bằng n.substr(0, i)và cũng number.toFixed(dp).split('.')[1]thay thế bằng parseFloat(number).toFixed(dp).split('.')[1]. bởi vì khi tôi sử dụng trực tiếp, nó sẽ báo lỗi. vui lòng cập nhật mã của bạn
Jignesh Sanghani

thiếu sót. số lượng tăng lên. một cuộc gọi exampel sẽ là tuyệt vời!
mmm

chuyển trần sang sàn cố định mà không chắc chắn những vấn đề khác sẽ phát sinh.
mmm

1
Hãy thử Math.floor (-75.1);)
mmm

4

Tôi nghĩ rằng chức năng này sẽ giải quyết tất cả các vấn đề liên quan đến vấn đề này.

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

4

Chỉ dành cho nhân viên Google trong tương lai (hoặc không nhất thiết phải là 'Nhân viên của Google'):

Tất cả các giải pháp được đề cập ở trên đều tuyệt vời, tuy nhiên, RegExp có thể là điều cực kỳ tồi tệ khi sử dụng trong tình huống như vậy.

Vì vậy, vâng, bạn có thể sử dụng một số tùy chọn được đề xuất hoặc thậm chí viết một cái gì đó nguyên thủy nhưng hữu ích như:

const strToNum = str => {

   //Find 1-3 digits followed by exactly 3 digits & a comma or end of string
   let regx = /(\d{1,3})(\d{3}(?:,|$))/;
   let currStr;

   do {
       currStr = (currStr || str.split(`.`)[0])
           .replace( regx, `$1,$2`)
   } while (currStr.match(regx)) //Stop when there's no match & null's returned

   return ( str.split(`.`)[1] ) ?
           currStr.concat(`.`, str.split(`.`)[1]) :
           currStr;

};

strToNum(`123`) // => 123
strToNum(`123456`) // => 123,456
strToNum(`-1234567.0987`) // => -1,234,567.0987

Regrec được sử dụng ở đây khá đơn giản và vòng lặp sẽ đi chính xác số lần cần thiết để hoàn thành công việc.

Và bạn có thể tối ưu hóa nó tốt hơn nhiều, mã "DRYify", v.v.

Chưa,

(-1234567.0987).toLocaleString();

(trong hầu hết các tình huống) sẽ là một lựa chọn tốt hơn nhiều.

Điểm không nằm ở tốc độ thực thi hoặc khả năng tương thích giữa nhiều trình duyệt.

Trong các trường hợp khi bạn muốn hiển thị số kết quả cho người dùng, phương thức .toLocaleString () cung cấp cho bạn siêu năng lực để nói cùng ngôn ngữ với người dùng trang web hoặc ứng dụng của bạn (bất kể ngôn ngữ của cô ấy / anh ấy là gì).

Phương pháp này theo tài liệu ECMAScript được giới thiệu vào năm 1999 và tôi tin rằng lý do cho điều đó là hy vọng rằng Internet tại một thời điểm nào đó sẽ kết nối mọi người trên khắp thế giới, vì vậy, cần có một số công cụ "nội địa hóa".

Ngày nay, Internet kết nối tất cả chúng ta, vì vậy, điều quan trọng cần nhớ là thế giới phức tạp hơn chúng ta có thể tưởng tượng và rằng (/ gần như) tất cả chúng ta đều ở đây , trên Internet.

Rõ ràng, xem xét sự đa dạng của mọi người, không thể đảm bảo UX hoàn hảo cho mọi người vì chúng tôi nói các ngôn ngữ khác nhau, coi trọng những thứ khác nhau, v.v. Và chính vì điều này, điều quan trọng hơn nữa là cố gắng bản địa hóa mọi thứ càng nhiều càng tốt .

Vì vậy, xem xét rằng có một số tiêu chuẩn cụ thể để thể hiện ngày, thời gian, số, v.v. & rằng chúng tôi có một công cụ để hiển thị những thứ đó theo định dạng được người dùng cuối ưa thích, không phải là hiếm và gần như vô trách nhiệm sử dụng công cụ đó (đặc biệt trong các tình huống khi chúng tôi muốn hiển thị dữ liệu này cho người dùng)?

Đối với tôi, sử dụng RegExp thay vì .toLocaleString () trong trường hợp nghe có vẻ hơi giống với việc tạo một ứng dụng đồng hồ bằng JavaScript và mã hóa nó theo cách như vậy để nó chỉ hiển thị thời gian ở Prague (sẽ khá vô dụng đối với những người không sống ở Prague) mặc dù hành vi mặc định của

new Date();

là để trả về dữ liệu theo đồng hồ của người dùng cuối cùng.


Tại sao bạn viết hàm với const và =>?
OG Sean

@OGSean Tôi luôn luôn làm vì đó là cách khai báo biến & hàm thuận tiện nhất. Ngoài ra, tôi nghĩ rằng nó giúp giữ cho mã sạch hơn và ngắn hơn.
Igor Bykov

4

My đúng thường xuyên-biểu-only giải pháp cho những tình yêu một lớp lót

Bạn thấy những người chơi nhiệt tình ở trên? Có lẽ bạn có thể chơi golf từ nó. Đây là đột quỵ của tôi.

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

Sử dụng một MỎNG SPACE (U + 2009) cho một phân cách hàng ngàn, như si nói để làm trong phiên bản thứ tám (2006) công bố họ “ SI Brochure: Các si (SI) ” (Xem §5.3 .4.). Phiên bản thứ chín (2019) đề nghị sử dụng một khoảng trắng cho nó (Xem §5.4.4.). Bạn có thể sử dụng bất cứ thứ gì bạn muốn, bao gồm cả dấu phẩy.


Xem.

const integer_part_only = n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ");
const fractional_part_only = n => `${n}`.replace(/(?<=\.(\d{3})+)\B/g, " F ");
const both = n => fractional_part_only(integer_part_only(n));

function demo(number) { // I’m using Chrome 74.
	console.log(`${number}
		 "${integer_part_only(number)}" (integer part only)
		 "${fractional_part_only(number)}" (fractional part only)
		 "${both(number)}" (both)
	`);
}
demo(Math.random() * 10e5);
demo(123456789.01234567);
demo(123456789);
demo(0.0123456789);


Làm thế nào nó hoạt động?

Đối với một phần nguyên

.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ")
  • .replace(……, " I ") Đưa tôi "
    • /……/g tại mỗi
      • \B ở giữa hai chữ số liền kề
        • (?=……)LOOKAHEAD TÍCH CỰC có phần bên phải là
          • (\d{3})+ một hoặc nhiều khối ba chữ số
          • \b theo sau là một chữ số, chẳng hạn như, một dấu chấm, kết thúc của chuỗi, et cetera,
        • (?<!……)TÌM KIẾM NEGECT trừ những người có phần bên trái
          • \.\d+ là một dấu chấm theo sau bởi các chữ số (Có một dấu phân cách thập phân).

Đối với một phần thập phân

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ") Đặt F F FII
    • /……/g tại mỗi
      • \B ở giữa hai chữ số liền kề
        • (?<=……)TÌM KIẾM TÍCH CỰC có phần bên trái là
          • \. dấu phân cách thập phân
          • (\d{3})+ theo sau là một hoặc nhiều khối ba chữ số.

Các lớp nhân vậtranh giới

\d

Phù hợp với bất kỳ chữ số (chữ số Ả Rập). Tương đương với [0-9].

Ví dụ,

  • /\d/hoặc /[0-9]/phù hợp 2trong B2 is the suite number.

\b

Phù hợp với một ranh giới từ . Đây là vị trí mà một ký tự từ không được theo sau hoặc đứng trước một ký tự từ khác, chẳng hạn như giữa một chữ cái và khoảng trắng. Lưu ý rằng một ranh giới từ phù hợp không được bao gồm trong trận đấu. Nói cách khác, độ dài của một ranh giới từ phù hợp bằng không.

Ví dụ:

  • /\bm/phù hợp với mtrong moon;
  • /oo\b/không khớp với chữ ooin moon, vì ootheo sau nlà ký tự từ;
  • /oon\b/khớp với phần oontrong moon, vì oonlà phần cuối của chuỗi, do đó không được theo sau bởi một ký tự từ;
  • /\w\b\w/ sẽ không bao giờ khớp với bất cứ điều gì, bởi vì một ký tự từ không bao giờ có thể được theo sau bởi cả ký tự không phải từ và ký tự từ.

\B

Phù hợp với một ranh giới không từ . Đây là một vị trí trong đó ký tự trước và ký tự tiếp theo cùng loại: cả hai đều phải là từ hoặc cả hai phải là từ không. Chẳng hạn như giữa hai chữ cái hoặc giữa hai không gian. Đầu và cuối của một chuỗi được coi là không từ. Giống như ranh giới từ phù hợp, ranh giới không từ phù hợp cũng không được bao gồm trong kết quả khớp.

Ví dụ,

  • /\Bon/ diêm on trong at noon;
  • /ye\B/phù hợp yetrong possibly yesterday.

Tính tương thích của trình duyệt web


3

Tôi đã thêm tofixed vào giải pháp của Aki143S . Giải pháp này sử dụng dấu chấm cho hàng ngàn dấu phân cách và dấu phẩy cho độ chính xác.

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(''); 
};

Ví dụ;

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

3

Rất nhiều câu trả lời hay. Đây là một thứ khác, chỉ để cho vui:

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] : "");
}

Vài ví dụ:

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

điều này không hoạt động với format(-123456)nó mang lại-,123,456
wrossmck

1
Đã sửa lỗi (mặc dù có thể có một cách thanh lịch hơn để làm điều đó mà không cần kiểm tra dấu hiệu mỗi lần). Trong mọi trường hợp, bản cập nhật làm cho công việc này với số âm.
Wayne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.