Câu hỏi Làm thế nào tôi có thể định dạng số như chuỗi tiền tệ đô la trong JavaScript?


Tôi muốn định dạng giá bằng JavaScript.
Tôi muốn có một chức năng float làm đối số và trả về string được định dạng như sau:

"$ 2,500.00"

Cách tốt nhất để làm điều này là gì?


1390


gốc


Không có chức năng tích hợp formatNumber trong javascript - zerkms
Xin vui lòng, cho bất cứ ai đọc điều này trong tương lai, làm không phải sử dụng float để lưu trữ tiền tệ. Bạn sẽ mất chính xác và dữ liệu. Bạn nên lưu trữ nó như một số nguyên của xu (hoặc đồng xu vv) và sau đó chuyển đổi trước khi đầu ra. - Philip Whitehouse
@ user1308743 Float không lưu trữ các vị trí thập phân. Nó lưu trữ số bằng cách sử dụng một giá trị, cơ sở và bù đắp. 0,01 là không thực sự đại diện. Xem: en.wikipedia.org/wiki/Floating_point#Accuracy_problems - Philip Whitehouse
@ user1308743: Hãy tưởng tượng bạn đại diện cho một số lượng rất lớn (cho phép nói rằng bạn là một anh chàng may mắn và đó là số dư tài khoản ngân hàng của bạn). Bạn có thực sự muốn mất tiền vì thiếu chính xác không? - ereOn
Vậy tại sao không có ai đề xuất như sau? (2500) .toLocaleString ("en-GB", {style: "tiền tệ", tiền tệ: "GBP", minimumFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Nick Grealy


Các câu trả lời:


Bạn có thể dùng:

  var profits=2489.8237
  profits.toFixed(3) //returns 2489.824 (round up)
  profits.toFixed(2) //returns 2489.82
  profits.toFixed(7) //returns 2489.8237000 (padding)

Sau đó, bạn có thể thêm dấu '$'.

Nếu bạn yêu cầu ',' cho hàng ngàn bạn có thể sử dụng:

Number.prototype.formatMoney = function(c, d, t){
    var n = this, 
    c = isNaN(c = Math.abs(c)) ? 2 : c, 
    d = d == undefined ? "." : d, 
    t = t == undefined ? "," : t, 
    s = n < 0 ? "-" : "", 
    i = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(c))), 
    j = (j = i.length) > 3 ? j % 3 : 0;
   return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
 };

Và sử dụng nó với:

(123456789.12345).formatMoney(2, '.', ',');

Nếu bạn luôn sử dụng '.' và ',', bạn có thể để chúng khỏi cuộc gọi phương thức của bạn và phương thức sẽ mặc định chúng cho bạn.

(123456789.12345).formatMoney(2);

Nếu văn hóa của bạn có hai biểu tượng bị lật (tức là người châu Âu), chỉ cần dán hai dòng sau vào formatMoney phương pháp:

    d = d == undefined ? "," : d, 
    t = t == undefined ? "." : t, 

1516



đầu tiên, tuyệt vời, súc tích mã. tuy nhiên, nếu bạn là người Mỹ, bạn nên thay đổi giá trị mặc định của d và t được . và , tương ứng để bạn không phải chỉ định chúng mỗi lần. ngoài ra, tôi khuyên bạn nên sửa đổi phần đầu của return tuyên bố để đọc: return s + '$' + [rest], nếu không bạn sẽ không nhận được một ký hiệu đô la. - Jason
Không chắc tại sao mọi người nghĩ mã này là đẹp. Nó là không thể giải mã được. Nó có vẻ hoạt động tốt, nhưng nó không đẹp. - usr
Chức năng formatMoney này có được sao chép từ một số mã JavaScript được rút gọn ở đâu đó không? Bạn không thể gửi bản gốc? Các biến c, d, i, j, n, s và t là gì? Đánh giá bởi số lượng upvotes và ý kiến ​​bài đăng này tôi có thể giả định mã này đã được sao chép dán vào các trang web sản xuất ở khắp mọi nơi ... Chúc may mắn duy trì mã nếu nó có một lỗi một ngày nào đó! - zuallauz
"thơ phú"? Giống như tối tăm. Đây không phải là chơi golf; sử dụng một khoảng trắng nhỏ. Tên var thích hợp cũng không bị tổn thương. - keithjgrant
Bất kỳ kẻ ngốc nào cũng có thể viết mã mà máy tính có thể hiểu được. Lập trình viên giỏi viết mã mà con người có thể hiểu được - Liam


Giải pháp ngắn và nhanh (hoạt động ở mọi nơi!)

(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');  // 12,345.67

Ý tưởng đằng sau giải pháp này là thay thế các phần phù hợp bằng dấu phẩy và dấu phẩy đầu tiên, tức là '$&,'. Kết hợp được thực hiện bằng cách sử dụng phương pháp tiếp cận lookahead. Bạn có thể đọc các biểu thức như "khớp một số nếu nó được theo sau bởi một chuỗi gồm ba tập hợp số (một hoặc nhiều) và một dấu chấm".

KIỂM TRA:

1        --> "1.00"
12       --> "12.00"
123      --> "123.00"
1234     --> "1,234.00"
12345    --> "12,345.00"
123456   --> "123,456.00"
1234567  --> "1,234,567.00"
12345.67 --> "12,345.67"

BẢN GIỚI THIỆU:  http://jsfiddle.net/hAfMM/9571/


Giải pháp ngắn mở rộng

Bạn cũng có thể mở rộng nguyên mẫu Number đối tượng để thêm hỗ trợ bổ sung cho bất kỳ số thập phân nào [0 .. n] và kích thước của các nhóm số [0 .. x]:

/**
 * Number.prototype.format(n, x)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of sections
 */
Number.prototype.format = function(n, x) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};

1234..format();           // "1,234"
12345..format(2);         // "12,345.00"
123456.7.format(3, 2);    // "12,34,56.700"
123456.789.format(2, 4);  // "12,3456.79"

DEMO / TESTS:  http://jsfiddle.net/hAfMM/435/


Giải pháp ngắn siêu mở rộng

Trong này siêu phiên bản mở rộng bạn có thể đặt các loại phân cách khác nhau:

/**
 * Number.prototype.format(n, x, s, c)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of whole part
 * @param mixed   s: sections delimiter
 * @param mixed   c: decimal delimiter
 */
Number.prototype.format = function(n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
        num = this.toFixed(Math.max(0, ~~n));

    return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};

12345678.9.format(2, 3, '.', ',');  // "12.345.678,90"
123456.789.format(4, 4, ' ', ':');  // "12 3456:7890"
12345678.9.format(0, 3, '-');       // "12-345-679"

DEMO / TESTS:  http://jsfiddle.net/hAfMM/612/


1022



Tôi thực sự đã đi thêm một bước: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"). - kalisjoshua
Phiên bản CoffeeScript với VisioN & kalisjoshua regexp và cách chỉ định vị trí thập phân (vì vậy bạn có thể để mặc định là 2 hoặc chỉ định 0 không có số thập phân): Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1," - Eric Anderson
@Abbas Yeah, thay thế \. với $ (cuối dòng), tức là this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,"). - VisioN
@hanumant Ngữ pháp thông thường có một chút phức tạp ở đây, vì vậy tôi khuyên bạn nên đọc hướng dẫn sử dụng về các biểu thức chính quy trước (ví dụ: MDN). Ý tưởng đằng sau nó thay thế các phần phù hợp bằng dấu phẩy và dấu phẩy đầu tiên, tức là $1,. Kết hợp được thực hiện bằng cách sử dụng phương pháp tiếp cận lookahead. Bạn có thể đọc các biểu thức như "khớp một số nếu nó được theo sau bởi một chuỗi gồm ba tập hợp số (một hoặc nhiều) và một dấu chấm". - VisioN
@ JuliendePrabère Xin vui lòng cho một ví dụ về một số dài mà không làm việc với phương pháp này. - VisioN


Intl.numberformat

Javascript có trình định dạng số và là một phần của API quốc tế hóa.

// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  // the default value for minimumFractionDigits depends on the currency
  // and is usually already 2
});

formatter.format(2500); /* $2,500.00 */

JS fiddle

Một số ghi chú về hỗ trợ trình duyệt

  • Tất cả các trình duyệt chính hỗ trợ nó ngày nay
  • Những người phạm tội lớn nhất về hỗ trợ là UC Mobile (tránh xa điều đó) và Opera Mini (bị tê liệt bởi thiết kế)
  • Đây là một shim để hỗ trợ nó trên các trình duyệt cũ hơn
  • Hãy xem CanIUse để biết thêm thông tin

Intl.NumberFormat vs Number.prototype.toLocaleString

Một lưu ý cuối cùng so sánh này với cũ hơn.toLocaleString. Cả hai đều cung cấp cơ bản các chức năng tương tự. Tuy nhiên, toLocaleString trong các hóa thân cũ hơn của nó (pre-Intl) không thực sự hỗ trợ ngôn ngữ: nó sử dụng ngôn ngữ hệ thống. Do đó, để đảm bảo rằng bạn đang sử dụng đúng phiên bản, MDN đề nghị kiểm tra sự tồn tại của Intl. Vì vậy, nếu bạn cần phải kiểm tra Intl anyway, tại sao không sử dụng  thay thế? Tuy nhiên, nếu bạn chọn sử dụng shim, đó cũng là các bản vá lỗi toLocaleString, vì vậy trong trường hợp đó bạn có thể sử dụng nó mà không gặp bất kỳ rắc rối nào:

(2500).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD',
}); /* $2,500.00 */

761



Giải pháp JavaScript đơn giản, đơn giản và thanh lịch này chính xác là những gì tôi đang tìm kiếm. - Guilhem Soulas
không đáng tin cậy trên safari - chulian
Tôi thích điều này, nhưng hãy kiểm tra hỗ trợ trước khi bạn sử dụng nó: caniuse.com/#feat=internationalization - jocull
Bỏ phiếu này vì nó là một câu trả lời đơn giản ngớ ngẩn hoạt động nguyên bản. - Trasiva
Khá chắc chắn một số lượng khá cao của trình duyệt bây giờ hỗ trợ này. Điều này nên được upvoted nhiều hơn nữa. - flq


Hãy xem JavaScript Con số và xem liệu nó có thể giúp bạn không.

  • toLocaleString() sẽ định dạng một số bằng cách sử dụng dấu phân tách hàng nghìn vị trí cụ thể.
  • toFixed() sẽ làm tròn số tới một số vị trí thập phân cụ thể.

Để sử dụng các giá trị này cùng một lúc, giá trị phải có kiểu của nó đã thay đổi trở lại thành một số vì chúng đều xuất ra một chuỗi.

Thí dụ:

Number(someNumber.toFixed(1)).toLocaleString()

160



Cảm ơn! Dựa trên ý tưởng này, tôi đã có thể tạo ra một ý tưởng ngắn và đơn giản! (và bản địa hóa) Tuyệt vời. - Daniel Magliola
Trên thực tế bạn có thể. ví dụ: đối với đô la: '$' + (giá trị 0,001) .toLocaleString (). slice (0, -1) - Zaptree
Có vẻ như nó sẽ tuyệt vời, nhưng hiện tại có rất ít trình duyệt hỗ trợ - acorncom
@acorncom Tại sao bạn nói có "hỗ trợ trình duyệt nhỏ"? Đối tượng Number đã có từ Javascript 1.1. Vui lòng cung cấp tham chiếu sao lưu khiếu nại của bạn. - Doug S
Cần lưu ý rằng có một phiên bản cũ của toLocaleString sử dụng ngôn ngữ hệ thống và một địa chỉ mới (không tương thích) đến từ API ECMAScript Intl. Giải thích ở đây. Câu trả lời này dường như dành cho phiên bản cũ. - aross


Dưới đây là Patrick Desjardins (bí danh Daok) mã với một chút ý kiến ​​được thêm vào và một số thay đổi nhỏ:

/* 
decimal_sep: character used as deciaml separtor, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{ 
   var n = this,
   c = isNaN(decimals) ? 2 : Math.abs(decimals), //if decimal is zero we must take it, it means user does not want to show any decimal
   d = decimal_sep || '.', //if no decimal separator is passed we use the dot as default decimal separator (we MUST use a decimal separator)

   /*
   according to [https://stackoverflow.com/questions/411352/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
   the fastest way to check for not defined parameter is to use typeof value === 'undefined' 
   rather than doing value === undefined.
   */   
   t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, //if you don't want to use a thousands separator you can pass empty string as thousands_sep value

   sign = (n < 0) ? '-' : '',

   //extracting the absolute value of the integer part of the number and converting to string
   i = parseInt(n = Math.abs(n).toFixed(c)) + '', 

   j = ((j = i.length) > 3) ? j % 3 : 0; 
   return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); 
}

và ở đây một số xét nghiệm:

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));

Những thay đổi nhỏ là:

  1. di chuyển một chút Math.abs(decimals) chỉ được thực hiện khi không NaN.

  2. decimal_sep không thể để trống chuỗi nữa (một loại phân cách thập phân nào đó là PHẢI)

  3. chúng tôi sử dụng typeof thousands_sep === 'undefined' như được đề xuất trong Cách tốt nhất để xác định xem đối số không được gửi đến hàm JavaScript

  4. (+n || 0) không cần thiết vì this là một Number vật


157



Bạn có thể muốn sử dụng '10' làm cơ số trong parseInt. Nếu không, bất kỳ số nào bắt đầu bằng '0' sẽ sử dụng đánh số bát phân. - sohtimsso1970
@ sohtimsso1970: xin lỗi vì phản hồi muộn, nhưng bạn có thể giải thích thêm một chút không? Tôi không thấy một số có thể được hiểu là bát phân. Các parseInt được gọi trên giá trị tuyệt đối của phần INTEGER của số. Phần INTEGER không thể bắt đầu với ZERO trừ khi nó chỉ là một ZERO! Và parseInt(0) === 0 bát phân hoặc thập phân. - Marco Demaio
hãy thử, ví dụ: parseInt ("016") ... trả về 14, vì parseInt giả định nó được mã hóa bát phân, khi chuỗi bắt đầu bằng số không. - Tracker1
@ Tracker1: Tôi hiểu rằng một số bắt đầu bằng 0 được coi là bát phân bởi parseInt. Nhưng trong mã này là không thể cho parseInt Nhận 016 làm đầu vào (hoặc bất kỳ giá trị định dạng bát phân nào khác), bởi vì đối số được chuyển đến parseInt được xử lý lần đầu bởi Math.abs chức năng. Cho nên không có cách nào cho parseInt để nhận một số bắt đầu bằng số không, trừ khi nó chỉ bằng 0 hoặc 0.nn (Ở đâu nn là số thập phân). Nhưng cả hai 0 và 0.nn chuỗi sẽ được chuyển đổi bởi parseInt thành một ZERO đơn giản như được cho là. - Marco Demaio
Hàm này không đúng:> (2030) .toMoney (0, '.', ''); <"2 03 0" - Anton P Robul


accounting.js là một thư viện JavaScript nhỏ để định dạng số, tiền và tiền tệ.


120



... chỉ cần nhớ để vượt qua một biểu tượng tiền tệ nếu không nó lỗi trong IE7 và IE8, IE9 là tốt, hoặc cách - vector
Có vẻ như lỗi IE7 / IE8 đã được sửa. - Mat Schaffer
Đây là một thư viện tuyệt vời, có thể vượt qua biểu tượng tiền tệ cũng là một ý tưởng tốt, vì tất cả các chi tiết tiền tệ được chứa trong các cuộc gọi / cài đặt chức năng duy nhất - farinspace
Tôi thích thực tế là bạn có thể làm ngược lại - chuyển một chuỗi tiền tệ được định dạng và nhận giá trị số. - Neil Monroe
accounting.js dường như không được duy trì gần đây. Một ngã ba với những thay đổi gần đây là github.com/nashdot/accounting-js - RationalDev


Đây là định dạng tiền js tốt nhất mà tôi từng thấy:

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
    var n = this,
        decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
        decSeparator = decSeparator == undefined ? "." : decSeparator,
        thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;
    return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};

Nó đã được định dạng lại và mượn từ đây: https://stackoverflow.com/a/149099/751484

Bạn sẽ phải cung cấp công cụ định giá tiền tệ của riêng bạn (bạn đã sử dụng $ ở trên).

Gọi nó như thế này (mặc dù lưu ý rằng args mặc định là 2, dấu phẩy và dấu chấm, do đó bạn không cần phải cung cấp bất kỳ arg nếu đó là sở thích của bạn):

var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"

95



xem ra cho globals ký, i, j - hacklikecrack
@hacklikecrack, tất cả các biến đều là cục bộ; họ đang ở trong var tuyên bố. - Jonathan M
xin lỗi, có, mặc dù bạn đang redeclaring đối số. Thụt lề! ;) - hacklikecrack
Sử dụng khủng khiếp các tên biến! - Serj Sagan


Nếu số tiền là số, hãy nói -123, sau đó

amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });

sẽ sản xuất chuỗi "-$123.00".

Đây là một công việc hoàn chỉnh thí dụ.


95



Câu trả lời này gần như là có cho tôi, nhưng tôi cần nó được làm tròn đến đồng xu gần nhất. Đây là những gì tôi đã sử dụng amount.toLocaleString ('en-GB', {style: 'currency', currency: 'GBP', maximumFractionDigits: 2}); - Nico
Đoạn mã trên làm tròn số chữ số bạn muốn. Xem ví dụ và gõ 1.237 vào hộp nhập liệu. - Daniel Barbalace
Dường như không hoạt động trong Safari. Nó chỉ trả về số dưới dạng Chuỗi mà không có bất kỳ định dạng nào. - Lance Anderson
Các Tài liệu MDN cho bất kỳ ai muốn xem toàn bộ các tùy chọn. - Mark Carpenter Jr
Wow, đây là một câu trả lời thực sự tuyệt vời. Nên là hàng đầu. - Ethan