Làm thế nào để định dạng số dưới dạng chuỗi tiền tệ?


1846

Tôi muốn định dạng một mức giá trong JavaScript. Tôi muốn một hàm lấy một floatđối số và trả về một stringđịnh dạng như thế này:

"$ 2,500.00"

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


8
Không có chức năng tích hợp formatNumbertrong javascript
zerkms

500
Xin vui lòng, cho bất cứ ai đọc điều này trong tương lai, không 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ó dưới dạng số xu nguyên (hoặc đồng xu, v.v.) và sau đó chuyển đổi trước khi xuất.
Philip Whitehouse

8
@ user1308743 Float không lưu trữ số 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 không thực sự đại diện. Xem: vi.wikipedia.org/wiki/Floating_point#Accuracy_probols
Philip Whitehouse

6
@ user1308743: Hãy tưởng tượng bạn đại diện cho một con số rất lớn (giả sử bạn là một người 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ì sự thiếu hụt chính xác?
vào

163
Vậy tại sao không ai đề xuất những điều sau đây? (2500) .toLocaleString ("en-GB", {style: "tệ", tiền tệ: "GBP", minimFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Nick Grealy

Câu trả lời:


1792

Number.prototype.toFixed

Giải pháp này tương thích với mọi trình duyệt chính duy nhất:

  const profits = 2489.8237;

  profits.toFixed(3) //returns 2489.824 (rounds up)
  profits.toFixed(2) //returns 2489.82
  profits.toFixed(7) //returns 2489.8237000 (pads the decimals)

Tất cả những gì bạn cần là thêm ký hiệu tiền tệ (ví dụ "$" + profits.toFixed(2)) và bạn sẽ có số tiền của mình bằng đô la.

Chức năng tùy chỉnh

Nếu bạn yêu cầu sử dụng ,giữa mỗi chữ số, bạn có thể sử dụng chức năng này:

function formatMoney(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;

return sign +
	(j ? i.substr(0, j) + thouSep : "") +
	i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "$1" + thouSep) +
	(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}

document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>

Sử dụng nó như vậy:

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

Nếu bạn luôn sử dụng '.' và ',', bạn có thể loại bỏ chúng khỏi cuộc gọi phương thức của mình 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 được lật (tức là người châu Âu) và bạn muốn sử dụng mặc định, chỉ cần dán qua hai dòng sau trong formatMoneyphương thức:

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

Chức năng tùy chỉnh (ES6)

Nếu bạn có thể sử dụng cú pháp ECMAScript hiện đại (tức là thông qua Babel), bạn có thể sử dụng chức năng đơn giản hơn này để thay thế:

function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
  try {
    decimalCount = Math.abs(decimalCount);
    decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

    const negativeSign = amount < 0 ? "-" : "";

    let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
    let j = (i.length > 3) ? i.length % 3 : 0;

    return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
  } catch (e) {
    console.log(e)
  }
};
document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>


26
trước hết, xuất sắc, mã súc tích. Tuy nhiên, nếu bạn là người Mỹ, bạn nên thay đổi giá trị mặc định của dt.,tương ứng để bạn không cần phải xác định chúng mọi lúc. Ngoài ra, tôi khuyên bạn nên sửa đổi phần đầu của returncâu lệnh để đọc: return s + '$' + [rest]nếu không, bạn sẽ không nhận được ký hiệu đô la.
Jason

744
Không chắc chắn tại sao mọi người nghĩ mã này là đẹp. Nó không thể giải mã được. Nó có vẻ hoạt động tốt, nhưng nó không đẹp.
usr

86
Hàm formatMoney này có được sao chép từ một số mã JavaScript được rút gọn ở đâu đó không? Bạn có thể không đăng bản gốc? Các biến c, d, i, j, n, s và t là gì? Đánh giá về số lượng upvote và bình luận bài đăng này tôi có thể cho rằng 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 một ngày nào đó có lỗi!
zuallauz

259
"thơ"? Giống như tối nghĩa hơn. Đây không phải là mã golf; sử dụng một chút khoảng trắng. Tên var đúng sẽ không bị tổn thương.
keithjgrant


1515

Intl.numberformat

Javascript có một bộ định dạng số (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',
});

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

Fiddle

Sử dụng undefinedthay cho đối số đầu tiên ('en-US' trong ví dụ) để sử dụng ngôn ngữ hệ thống (ngôn ngữ người dùng trong trường hợp mã đang chạy trong trình duyệt). Giải thích thêm về mã địa phương .

Đây là một danh sách các mã tiền tệ .

Intl.NumberFormat vs Number.prototype.toLocaleString

Một lưu ý cuối cùng so sánh điều này với cũ. toLocaleString. Cả hai đều cung cấp về cơ bản cùng một chức năng. Tuy nhiên, toLocaleString trong các phiên bản cũ hơn (tiền quốc tế) không thực sự hỗ trợ các ngôn ngữ : nó sử dụng ngôn ngữ hệ thống. Do đó, hãy chắc chắn rằng bạn đang sử dụng phiên bản chính xác ( MDN gợi ý để kiểm tra sự tồn tại củaIntl ). Ngoài ra, hiệu suất của cả hai là như nhau cho một đơn hàng, nhưng nếu bạn có rất nhiều con số sang định dạng, sử dụng Intl.NumberFormatlà ~ nhanh hơn 70 lần. Đây là cách sử dụng toLocaleString:

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

Một số lưu ý về hỗ trợ trình duyệt

  • Hiện tại, hỗ trợ trình duyệt không còn là vấn đề với 97,5% hỗ trợ trên toàn cầu, 98% ở Mỹ và 99% ở EU
  • Có một shim để hỗ trợ nó trên các trình duyệt hóa thạch (như IE8), nếu bạn thực sự cần phải
  • Hãy xem CanIUse để biết thêm thông tin

89
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

9
Bỏ phiếu này vì đây là một câu trả lời đơn giản ngu ngốc hoạt động nguyên bản.
Trasiva

17
Khá chắc chắn rằng một tỷ lệ khá cao các trình duyệt hiện hỗ trợ điều này. Điều này nên được nâng cao hơn nhiều.
flq

2
Đây là một câu trả lời tuyệt vời và tôi có nó hoạt động với giá trị tiền tệ động nên nếu sử dụng ở Châu Âu thì nó đổi thành EUR và hiển thị ký hiệu đồng euro. Làm việc một điều trị!
Phát sinh

3
Đó là năm 2018 và điều này về cơ bản được hỗ trợ ở mọi nơi. Đây phải là câu trả lời chính xác.
sarink

1340

Giải pháp ngắn và nhanh chóng (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 trùng khớp bằng dấu phẩy và dấu phẩy đầu tiên, nghĩa là '$&,'. Sự phù hợp được thực hiện bằng cách sử dụng phương pháp lookahead . Bạn có thể đọc biểu thức là "khớp một số nếu nó được theo sau bởi một chuỗi gồm ba bộ 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"

DEMO: 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 của Numberđối tượng để thêm hỗ trợ 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 / KIỂM TRA: http://jsfiddle.net/hAfMM/435/


Giải pháp siêu ngắn

Trong phiên bản siêu mở rộng này, bạn có thể đặt các loại dấu 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 / KIỂM TRA: http://jsfiddle.net/hAfMM/612/


21
Tôi thực sự đã đi một bước xa hơn : .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,").
kalisjoshua

4
Phiên bản CoffeeScript với VisioN & kalisjoshua regrec và cách chỉ định vị trí thập phân (để 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

11
@Abbas Vâng, thay thế \.bằng $(cuối dòng), nghĩa là this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,").
VisioN

2
@hanumant Ngữ pháp thông thường hơi 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 thông thường trước tiên (ví dụ tại MDN ). Ý tưởng đằng sau nó là thay thế các phần phù hợp bằng dấu phẩy và dấu phẩy đầu tiên, nghĩa là $1,. Sự phù hợp được thực hiện bằng cách sử dụng phương pháp lookahead . Bạn có thể đọc biểu thức là "khớp một số nếu nó được theo sau bởi một chuỗi gồm ba bộ số (một hoặc nhiều) và một dấu chấm" .
VisioN

2
@ JuliendePrabère Vui lòng cho một ví dụ về một số dài không hoạt động với phương pháp này.
VisioN

248

Hãy xem đối tượng Số JavaScript và xem 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 cách hàng nghìn vị trí cụ thể.
  • toFixed() sẽ làm tròn số đến một số thập phân cụ thể.

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

Thí dụ:

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

2
Cảm ơn! Dựa trên ý tưởng này, tôi đã có thể tạo ra một thứ đủ ngắn và đơn giản! (và bản địa hóa) Tuyệt vời.
Daniel Magliola

7
Thật ra bạn có thể. tức là đối với đô la: '$' + (giá trị + 0,001) .toLocaleString (). lát (0, -1)
Zaptree

6
Có vẻ như nó sẽ rất tuyệt, nhưng hiện tại có rất ít sự hỗ trợ của trình duyệt
acorncom

1
@acorncom Tại sao bạn nói có "hỗ trợ trình duyệt nhỏ"? Đối tượng Number đã xuất hiện kể từ Javascript 1.1. Vui lòng cung cấp một tài liệu tham khảo sao lưu yêu cầu của bạn.
Doug S

2
Cần lưu ý rằng có một phiên bản cũ toLocaleStringsử dụng ngôn ngữ hệ thống và phiên bản 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ư được dành cho phiên bản cũ.
vào

162

Dưới đây là mã Patrick Desjardins (bí danh Daok) với một chút bình luậ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 [/programming/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ố bài kiểm tra:

//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)để được thực hiện chỉ khi không NaN.

  2. decimal_sep không thể là chuỗi rỗng nữa (một loại dấu tá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 một đối số không được gửi đến hàm JavaScript

  4. (+n || 0)không cần thiết vì thislà một Numberđối tượng

Fiddle


8
Bạn có thể muốn sử dụng '10' làm cơ số trong parseInt. Mặt khác, bất kỳ số nào bắt đầu bằng '0' sẽ sử dụng đánh số bát phân.
sohtimsso1970

3
@ sohtimsso1970: xin lỗi vì phản hồi muộn, nhưng bạn có thể giải thích thêm không? Tôi không thấy nơi một số có thể được hiểu là bát phân. Các parseIntđược gọi vào 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à ZERO! Và parseInt(0) === 0bát phân hoặc thập phân.
Marco Demaio

thử, ví dụ: parseInt ("016") ... trả về 14, vì parseInt giả định rằng nó được mã hóa bát phân, khi chuỗi bắt đầu bằng 0.
Tracker1

4
@ 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à TÁC ĐỘNG parseIntđể nhận 016là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 truyền đến parseIntlà lần đầu tiên được xử lý bởi Math.abshàm. Vì vậy, không có cách nào parseIntđể nhận được một số bắt đầu bằng 0 trừ khi đó chỉ là số 0 hoặc 0.nn( nnsố thập phân). Nhưng cả hai 00.nnchuỗi sẽ được chuyển đổi parseIntthành một số KHÔNG đơn giản như được cung cấp.
Marco Demaio

Hàm này không chính xác:> (2030) .toMoney (0, '.', ''); <"2 03 0"
Anton P Robul 18/03/2016

124

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


... chỉ cần nhớ chuyển một ký hiệu tiền tệ nếu không nó bị lỗi trong IE7 và IE8, IE9 cũng không sao
vector

2
Có vẻ như lỗi IE7 / IE8 đã được sửa.
Mat Schaffer

2
Đâ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 hay, 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
khoảng cách

2
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

2
hạch toán 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 thích GoFundMonica

124

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

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

sẽ tạo ra chuỗi "-$123.00" .

Đây là một ví dụ hoạt động hoàn chỉnh .


7
Câu trả lời này gần như đã có đối với tôi, nhưng tôi cần nó được làm tròn đến đồng xu gần nhất. Đây là số tiền tôi đã sử dụng số tiền.toLocaleString ('en-GB', {style: 'tệ', tiền tệ: 'GBP', MaximumFractionDigits: 2});
Nico

Đoạn mã trên không làm tròn đến số chữ số bạn muốn. Xem ví dụ và nhập 1.237 vào hộp nhập.
Daniel Barbalace

3
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

1
Wow, đây là một câu trả lời thực sự tuyệt vời. Nên là hàng đầu.
Ethan

2
Nếu vì lý do nào đó bạn không muốn xu, bạn có thể thay đổi độ chính xác thập phân bằng:minimumFractionDigits: 0
Horacio

99

Đây là công cụ định dạng tiền js tốt nhất 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ụ chỉ định 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, vì vậy bạn không cần cung cấp bất kỳ đối số nào nếu đó là tùy chọn của bạn):

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

coi chừng ký hiệu toàn cầu, i, j
hacklikecrack

6
@hacklikecrack, tất cả các biến là cục bộ; Họ đang ở trong vartuyên bố.
Jonathan M

3
xin lỗi, vâng, mặc dù bạn đang tuyên bố lại lập luận. Thụt vào! ;)
hacklikecrack

Sử dụng khủng khiếp tên biến!
Serj Sagan

77

Đã có một số câu trả lời tuyệt vời ở đây. Đây là một nỗ lực khác, chỉ để cho vui:

function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    return "$" + p[0].split("").reverse().reduce(function(acc, num, i, orig) {
        return  num=="-" ? acc : num + (i && !(i % 3) ? "," : "") + acc;
    }, "") + "." + p[1];
}

Và một số bài kiểm tra:

formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"

Đã chỉnh sửa: bây giờ nó cũng sẽ xử lý các số âm


thơ. xuất sắc. Bạn đã thử giảmRight () developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ hay mà nên loại bỏ đảo ngược ()?
Steve

1
@Steve - Bạn nói đúng, nhưng bạn cần phải làm một cái gì đó như i = orig.length - i - 1trong cuộc gọi lại. Tuy nhiên, một ít đi qua các mảng.
Wayne

11
Không liên quan đến khả năng tương thích: reducePhương pháp được giới thiệu trong Ecmascript 1.8 và không được hỗ trợ trong Internet Explorer 8 trở xuống.
Blaise

Giống như @Blaise đã nói, phương pháp này sẽ không hoạt động trong IE 8 trở xuống.
rsbarro

Vâng, điều đó tất nhiên là đúng. Như đã lưu ý trong câu trả lời, đây chỉ là cho vui. Ngoài ra, nó nên xử lý số âm chỉ tốt.
Wayne

76

Hoạt động cho tất cả các trình duyệt hiện tại

Sử dụng toLocaleStringđể định dạng một loại tiền tệ trong biểu diễn nhạy cảm với ngôn ngữ (sử dụng tiền tệ ISO 4217 ).

(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2}) 

Ví dụ đoạn mã Rand của Nam Phi cho @avenmore

console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00


1
Bởi vì các đối số 'địa phương' và 'tùy chọn' chỉ được hỗ trợ bởi một số lượng nhỏ các trình duyệt, như Chrome 24, IE11 và Opera 15. Firefox, Safari và các phiên bản cũ hơn của những người khác vẫn không hỗ trợ nó.
VisioN

3
Đồng ý, nó chưa được hỗ trợ đầy đủ trên tất cả các trình duyệt (nhưng) vẫn là một giải pháp. (Và được cho là giải pháp hợp lệ nhất, vì nó tương thích với các trình duyệt không được hỗ trợ và đó là một tính năng được ghi lại của api Javascript.)
Nick Grealy

1
Tôi thích điều này và rất vui khi nó hoạt động với nhóm chữ số Ấn Độ.
MSC

7
Điều này được hỗ trợ đầy đủ kể từ năm 2017 và phải là câu trả lời đúng duy nhất
Evgeny

1
Mới nhất và lớn nhất :) FF69, Chrome76, v.v. "R 2 500,00" không phải là thứ chúng tôi sử dụng ở đây, nó phải là "R 2.500.00", giống như en-GB.
avenmore

70

Tôi nghĩ những gì bạn muốn là f.nettotal.value = "$" + showValue.toFixed(2);


@ nghiền điều này hoạt động nhưng nó không còn mang tính toán vào lĩnh vực thuế?
Rocco The Taco

11
Khi bạn thêm dấu $ vào nó, nó không còn là số mà là một chuỗi.
nghiền nát

Tùy chọn này không đặt dấu phẩy giữa hàng ngàn. :-(
Simon East


27

Ok, dựa trên những gì bạn nói, tôi đang sử dụng điều này:

var DecimalSeparator = Number("1.2").toLocaleString().substr(1,1);

var AmountWithCommas = Amount.toLocaleString();
var arParts = String(AmountWithCommas).split(DecimalSeparator);
var intPart = arParts[0];
var decPart = (arParts.length > 1 ? arParts[1] : '');
decPart = (decPart + '00').substr(0,2);

return '£ ' + intPart + DecimalSeparator + decPart;

Tôi sẵn sàng để đề xuất cải tiến (tôi không muốn bao gồm YUI chỉ để làm điều này :-)) Tôi đã biết rằng tôi nên phát hiện "." thay vì chỉ sử dụng nó như dấu phân cách thập phân ...


8
Lưu ý rằng phiên bản của bạn không làm tròn đúng đến hai chữ số thập phân. Ví dụ: 3.706 sẽ được định dạng là "£ 3,70", không phải là "£ 3,71" như dự kiến.
Ates Goral

Có, điều đó ổn trong trường hợp cụ thể của tôi, vì số tiền tôi đang làm việc đã có tối đa 2 chữ số Lý do tôi cần sửa thành 2 số thập phân là vì số tiền không có số thập phân hoặc chỉ có 1.
Daniel Magliola

26

Tôi sử dụng thư viện Toàn cầu hóa (từ Microsoft):

Đây là một dự án tuyệt vời để bản địa hóa các số, tiền tệ và ngày tháng và để chúng tự động được định dạng đúng cách theo địa điểm người dùng! ... và mặc dù nó phải là một phần mở rộng của jQuery, hiện tại nó là một thư viện độc lập 100%. Tôi đề nghị tất cả các bạn để thử nó! :)


3
Wow, tại sao điều này không được nâng cao hơn? Thư viện tiêu chuẩn lớn cho tất cả các loại định dạng. Các tham số định dạng tiêu chuẩn công nghiệp với toàn cầu hóa chính xác. Câu trả lời chính xác!!
pbarranis

Nó vẫn được coi là giai đoạn alpha, vì vậy hãy sử dụng một cách thận trọng, nhưng tìm thấy tuyệt vời.
Neil Monroe

1
Không còn ở dạng alpha (hoặc beta). Điều này có vẻ rất hữu ích trong khi chúng tôi chờ Safari đáp ứng tiêu chuẩn mới và IE <11 sẽ chết.
Guy Schalnat

25

javascript-number-formatter (trước đây tại Google Code )

  • Ngắn, nhanh, linh hoạt nhưng độc lập. Chỉ có 75 dòng bao gồm thông tin giấy phép MIT, dòng trống và bình luận.
  • Chấp nhận định dạng số chuẩn như #,##0.00hoặc có phủ định -000.####.
  • Chấp nhận bất kỳ định dạng quốc gia như # ##0,00, #,###.##, #'###.##hoặc bất kỳ loại hình biểu tượng không đánh số.
  • Chấp nhận bất kỳ số nào của nhóm chữ số. #,##,#0.000hoặc #,###0.##đều hợp lệ
  • Chấp nhận bất kỳ định dạng dự phòng / đánh lừa. ##,###,##.#hoặc 0#,#00#.###0#là tất cả OK.
  • Tự động làm tròn số.
  • Giao diện đơn giản, chỉ cần cung cấp mặt nạ & giá trị như thế này : format( "0.0000", 3.141592).
  • Bao gồm tiền tố & hậu tố với mặt nạ

(trích từ README của nó)


23

+1 cho Jonathan M để cung cấp phương thức ban đầu. Vì đây rõ ràng là một công cụ định dạng tiền tệ, tôi đã tiếp tục và thêm ký hiệu tiền tệ (mặc định là '$') vào đầu ra và thêm dấu phẩy mặc định là dấu phân cách hàng nghìn. Nếu bạn không thực sự muốn một ký hiệu tiền tệ (hoặc hàng ngàn dấu phân cách), chỉ cần sử dụng "" (chuỗi trống) làm đối số cho nó.

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
    // check the args and supply defaults:
    decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
    decSeparator = decSeparator == undefined ? "." : decSeparator;
    thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
    currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;

    var n = this,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;

    return sign + currencySymbol + (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) : "");
};

Var đầu tiên hơi lạ, vì các biến đó đã được khai báo trong khai báo hàm. Ngoài ra, cảm ơn!
Giàu Bradshaw

2
Bạn đúng. Đó là một lỗi tôi đã đưa ra từ bản gốc của Jonathan M, trong đó tất cả chúng đều bị xiềng xích dưới dạng một biểu thức var. Đó nên là những bài tập đơn giản. Sửa chữa.
XML

Đối với vấn đề đó, tôi nghĩ rằng điều này có lẽ được tối ưu hóa sớm và nên được tái cấu trúc để dễ đọc. Nhưng mục tiêu của tôi là tăng mã của OP, chứ không phải thay đổi căn bản.
XML

Nó không quá tệ - đó +n || 0là điều duy nhất có vẻ hơi kỳ lạ (với tôi dù thế nào đi nữa).
Bradshaw giàu có

2
thislà một tên biến hoàn toàn hữu ích. Chuyển đổi nó thành nđể bạn có thể lưu 3 ký tự ở thời điểm xác định có thể là cần thiết trong thời đại khi RAM và băng thông được tính bằng KB, nhưng chỉ đơn thuần là bị che khuất trong thời đại mà công cụ khai thác sẽ xử lý tất cả những gì trước khi nó bắt đầu sản xuất. Các tối ưu hóa vi thông minh khác ít nhất là gây tranh cãi.
XML

22

Có một cổng javascript của hàm PHP "number_format".

Tôi thấy nó rất hữu ích vì nó dễ sử dụng và dễ nhận biết cho các nhà phát triển PHP.

function number_format (number, decimals, dec_point, thousands_sep) {
    var n = number, prec = decimals;

    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };

    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); 
    //fix for IE parseFloat(0.55).toFixed(0) = 0;

    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;

    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;

        _[0] = s.slice(0,i + (n < 0)) +
               _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }

    var decPos = s.indexOf(dec);
    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
    }
    else if (prec >= 1 && decPos === -1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s; 
}

(Khối nhận xét từ bản gốc , bao gồm bên dưới cho ví dụ & tín dụng khi đến hạn)

// Formats a number with grouped thousands
//
// version: 906.1806
// discuss at: http://phpjs.org/functions/number_format
// +   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)
// *     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'

Đây chỉ là một hàm đúng:> number_format (2030, 0, '.', '') <'2 030' Tuyệt vời! Cảm ơn
Anton P Robul 18/03/2016

21

Một phương pháp ngắn hơn (để chèn không gian, dấu phẩy hoặc điểm) với biểu thức chính quy?

    Number.prototype.toCurrencyString=function(){
        return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g,'$1 ');
    }

    n=12345678.9;
    alert(n.toCurrencyString());

20

Không thấy bất cứ điều gì như thế này. Nó khá súc tích và dễ hiểu.

function moneyFormat(price, sign = '$') {
  const pieces = parseFloat(price).toFixed(2).split('')
  let ii = pieces.length - 3
  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, ',')
  }
  return sign + pieces.join('')
}

console.log(
  moneyFormat(100),
  moneyFormat(1000),
  moneyFormat(10000.00),
  moneyFormat(1000000000000000000)
)

Đây là phiên bản có nhiều tùy chọn hơn ở đầu ra cuối cùng để cho phép định dạng các loại tiền tệ khác nhau ở các định dạng địa phương khác nhau.

// higher order function that takes options then a price and will return the formatted price
const makeMoneyFormatter = ({
  sign = '$',
  delimiter = ',',
  decimal = '.',
  append = false,
  precision = 2,
  round = true,
  custom
} = {}) => value => {
  
  const e = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]
  
  value = round
    ? (Math.round(value * e[precision]) / e[precision])
    : parseFloat(value)
  
  const pieces = value
    .toFixed(precision)
    .replace('.', decimal)
    .split('')
  
  let ii = pieces.length - (precision ? precision + 1 : 0)
  
  while ((ii-=3) > 0) {
    pieces.splice(ii, 0, delimiter)
  }
  
  if (typeof custom === 'function') {
    return custom({
      sign,
      float: value, 
      value: pieces.join('') 
    })
  }
  
  return append
    ? pieces.join('') + sign
    : sign + pieces.join('')
}

// create currency converters with the correct formatting options
const formatDollar = makeMoneyFormatter()
const formatPound = makeMoneyFormatter({ 
  sign: '£',
  precision: 0
})
const formatEuro = makeMoneyFormatter({
  sign: '€',
  delimiter: '.',
  decimal: ',',
  append: true
})

const customFormat = makeMoneyFormatter({
  round: false,
  custom: ({ value, float, sign }) => `SALE:$${value}USD`
})

console.log(
  formatPound(1000),
  formatDollar(10000.0066),
  formatEuro(100000.001),
  customFormat(999999.555)
)


Đoạn mã tuyệt vời, cảm ơn bạn. Tuy nhiên, hãy cẩn thận, vì nó sẽ không hoạt động trên IE vì các tham số mặc định không được hỗ trợ và "const" và "let" không được hỗ trợ trong <IE11. Bạn phải sửa lỗi này: + moneyFormat: function (price, sign) {+ if (! Sign) sign = '$'; + Pieces = parseFloat (giá) .toFixed (2) .split ('') + var ii = Pieces.length - 3
Charlie Dalsass

Đừng lo lắng @CharlieDalsass. Tôi khuyên bạn nên sử dụng babel để biên dịch nó xuống ES5 cho mã sản xuất.
synthet1c

Nhưng làm thế nào để làm đồng tiền Euro? 1.000,00 Euro?

@YumYumYum Tôi đã thêm một ví dụ đầy đủ với nhiều tùy chọn định dạng hơn để cho phép linh hoạt hơn.
synthet1c

18

Câu trả lời của Patrick Desjardins có vẻ tốt, nhưng tôi thích javascript của tôi đơn giản. Đây là một chức năng tôi vừa viết để lấy một số và trả lại ở định dạng tiền tệ (trừ ký hiệu đô la)

// Format numbers to two decimals with commas
function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    var chars = p[0].split("").reverse();
    var newstr = '';
    var count = 0;
    for (x in chars) {
        count++;
        if(count%3 == 1 && count != 1) {
            newstr = chars[x] + ',' + newstr;
        } else {
            newstr = chars[x] + newstr;
        }
    }
    return newstr + "." + p[1];
}

Tôi cần một cái gì đó để hoạt động trong cả trình duyệt và trong phiên bản cũ của Node. Điều này làm việc hoàn hảo. Cảm ơn
n8jadams

17

Phần chính là chèn hàng nghìn dấu phân cách, có thể được thực hiện như thế này:

<script type="text/javascript">
function ins1000Sep(val){
  val = val.split(".");
  val[0] = val[0].split("").reverse().join("");
  val[0] = val[0].replace(/(\d{3})/g,"$1,");
  val[0] = val[0].split("").reverse().join("");
  val[0] = val[0].indexOf(",")==0?val[0].substring(1):val[0];
  return val.join(".");
}
function rem1000Sep(val){
  return val.replace(/,/g,"");
}
function formatNum(val){
  val = Math.round(val*100)/100;
  val = (""+val).indexOf(".")>-1 ? val + "00" : val + ".00";
  var dec = val.indexOf(".");
  return dec == val.length-3 || dec == 0 ? val : val.substring(0,dec+3);
}
</script>

<button onclick="alert(ins1000Sep(formatNum(12313231)));">

Tôi nhận được đầu ra số sai trong khi nhập giá trị âm vào ins1000Sep ().
Peter

16

Có một function toFixed tích hợp trongjavascript

var num = new Number(349);
document.write("$" + num.toFixed(2));

Câu trả lời này có vẻ dư thừa. Câu trả lời của Crush đã được nhắctoFixed()
Ian Dunn

3
toFixed()là một chức năng của Numberđối tượng và sẽ không hoạt động var numnếu nó là một String, vì vậy bối cảnh bổ sung đã giúp tôi.
timborden

15
function CurrencyFormatted(amount)
{
    var i = parseFloat(amount);
    if(isNaN(i)) { i = 0.00; }
    var minus = '';
    if(i < 0) { minus = '-'; }
    i = Math.abs(i);
    i = parseInt((i + .005) * 100);
    i = i / 100;
    s = new String(i);
    if(s.indexOf('.') < 0) { s += '.00'; }
    if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
    s = minus + s;
    return s;
}

Từ WillMaster .


Nhỏ và đơn giản. Cảm ơn bạn.
Connor Simpson

1
đơn giản, nhưng không có dấu phẩy cho 1.000
aron

15

Tôi đề nghị lớp NumberFormat từ Google Visualization API .

Bạn có thể làm một cái gì đó như thế này:

var formatter = new google.visualization.NumberFormat({
    prefix: '$',
    pattern: '#,###,###.##'
});

formatter.formatValue(1000000); // $ 1,000,000

Tôi hy vọng nó sẽ giúp.


14

Điều này có thể hơi muộn, nhưng đây là một phương pháp tôi vừa làm cho đồng nghiệp để thêm .toCurrencyString()chức năng nhận biết miền địa phương cho tất cả các số. Việc nội địa hóa chỉ dành cho nhóm số, KHÔNG phải là ký hiệu tiền tệ - nếu bạn xuất ra đô la, hãy sử dụng "$"như được cung cấp, bởi vì $123 4567ở Nhật Bản hoặc Trung Quốc có cùng số USD như $1,234,567ở Mỹ. Nếu bạn xuất ra đồng euro / v.v., thì hãy thay đổi ký hiệu tiền tệ từ đó "$".

Khai báo điều này ở bất cứ đâu trong ĐẦU của bạn hoặc bất cứ nơi nào cần thiết, ngay trước khi bạn cần sử dụng nó:

  Number.prototype.toCurrencyString = function(prefix, suffix) {
    if (typeof prefix === 'undefined') { prefix = '$'; }
    if (typeof suffix === 'undefined') { suffix = ''; }
    var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
    return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
  }

Vậy là xong! Sử dụng (number).toCurrencyString()bất cứ nơi nào bạn cần để xuất số dưới dạng tiền tệ.

var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"

12

Như thường lệ, có nhiều cách để làm điều tương tự nhưng tôi sẽ tránh sử dụng Number.prototype.toLocaleString vì nó có thể trả về các giá trị khác nhau dựa trên cài đặt của người dùng.

Tôi cũng không khuyên bạn nên mở Number.prototyperộng các nguyên mẫu - mở rộng đối tượng gốc là một cách làm xấu vì nó có thể gây xung đột với mã của người khác (ví dụ: thư viện / khung / plugin) và có thể không tương thích với các phiên bản / triển khai JavaScript trong tương lai.

Tôi tin rằng Biểu thức chính quy là cách tiếp cận tốt nhất cho vấn đề, đây là cách thực hiện của tôi:

/**
 * Converts number into currency format
 * @param {number} number   Number that should be converted.
 * @param {string} [decimalSeparator]    Decimal separator, defaults to '.'.
 * @param {string} [thousandsSeparator]    Thousands separator, defaults to ','.
 * @param {int} [nDecimalDigits]    Number of decimal digits, defaults to `2`.
 * @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
 */
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
    //default values
    decimalSeparator = decimalSeparator || '.';
    thousandsSeparator = thousandsSeparator || ',';
    nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;

    var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
        parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]

    if(parts){ //number >= 1000 || number <= -1000
        return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
    }else{
        return fixed.replace('.', decimalSeparator);
    }
}

chỉnh sửa vào ngày 2010/08/30: thêm tùy chọn để đặt số chữ số thập phân. chỉnh sửa vào ngày 23 tháng 8 năm 2011: thêm tùy chọn để đặt số chữ số thập phân thành không.


Điểm của toLocaleString là nó điều chỉnh theo cài đặt của người dùng.
Joseph Lennox

11

Dưới đây là một số giải pháp, tất cả đều vượt qua bộ kiểm tra, bộ kiểm tra và điểm chuẩn bao gồm, nếu bạn muốn sao chép và dán để kiểm tra, hãy thử This Gist .

Phương pháp 0 (RegExp)

Dựa trên https://stackoverflow.com/a/14428340/1877620 , nhưng sửa nếu không có dấu thập phân.

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');
        a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
        return a.join('.');
    }
}

Phương pháp 1

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.'),
            // skip the '-' sign
            head = Number(this < 0);

        // skip the digits that's before the first thousands separator 
        head += (a[0].length - head) % 3 || 3;

        a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
        return a.join('.');
    };
}

Phương pháp 2 (Tách thành mảng)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');

        a[0] = a[0]
            .split('').reverse().join('')
            .replace(/\d{3}(?=\d)/g, '$&,')
            .split('').reverse().join('');

        return a.join('.');
    };
}

Phương pháp 3 (Vòng lặp)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('');
        a.push('.');

        var i = a.indexOf('.') - 3;
        while (i > 0 && a[i-1] !== '-') {
            a.splice(i, 0, ',');
            i -= 3;
        }

        a.pop();
        return a.join('');
    };
}

Ví dụ sử dụng

console.log('======== Demo ========')
console.log(
    (1234567).format(0),
    (1234.56).format(2),
    (-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
    n = (n * 10) + (i % 10)/100;
    console.log(n.format(2), (-n).format(2));
}

Dấu phân cách

Nếu chúng tôi muốn phân tách hàng nghìn hoặc dấu phân cách tùy chỉnh, hãy sử dụng replace():

123456.78.format(2).replace(',', ' ').replace('.', ' ');

Bộ kiểm tra

function assertEqual(a, b) {
    if (a !== b) {
        throw a + ' !== ' + b;
    }
}

function test(format_function) {
    console.log(format_function);
    assertEqual('NaN', format_function.call(NaN, 0))
    assertEqual('Infinity', format_function.call(Infinity, 0))
    assertEqual('-Infinity', format_function.call(-Infinity, 0))

    assertEqual('0', format_function.call(0, 0))
    assertEqual('0.00', format_function.call(0, 2))
    assertEqual('1', format_function.call(1, 0))
    assertEqual('-1', format_function.call(-1, 0))
    // decimal padding
    assertEqual('1.00', format_function.call(1, 2))
    assertEqual('-1.00', format_function.call(-1, 2))
    // decimal rounding
    assertEqual('0.12', format_function.call(0.123456, 2))
    assertEqual('0.1235', format_function.call(0.123456, 4))
    assertEqual('-0.12', format_function.call(-0.123456, 2))
    assertEqual('-0.1235', format_function.call(-0.123456, 4))
    // thousands separator
    assertEqual('1,234', format_function.call(1234.123456, 0))
    assertEqual('12,345', format_function.call(12345.123456, 0))
    assertEqual('123,456', format_function.call(123456.123456, 0))
    assertEqual('1,234,567', format_function.call(1234567.123456, 0))
    assertEqual('12,345,678', format_function.call(12345678.123456, 0))
    assertEqual('123,456,789', format_function.call(123456789.123456, 0))
    assertEqual('-1,234', format_function.call(-1234.123456, 0))
    assertEqual('-12,345', format_function.call(-12345.123456, 0))
    assertEqual('-123,456', format_function.call(-123456.123456, 0))
    assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
    assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
    assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
    // thousands separator and decimal
    assertEqual('1,234.12', format_function.call(1234.123456, 2))
    assertEqual('12,345.12', format_function.call(12345.123456, 2))
    assertEqual('123,456.12', format_function.call(123456.123456, 2))
    assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
    assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
    assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
    assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
    assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
    assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
    assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
    assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
    assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}

console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);

Điểm chuẩn

function benchmark(f) {
    var start = new Date().getTime();
    f();
    return new Date().getTime() - start;
}

function benchmark_format(f) {
    console.log(f);
    time = benchmark(function () {
        for (var i = 0; i < 100000; i++) {
            f.call(123456789, 0);
            f.call(123456789, 2);
        }
    });
    console.log(time.format(0) + 'ms');
}

// if not using async, browser will stop responding while running.
// this will create a new thread to benchmark
async = [];
function next() {
    setTimeout(function () {
        f = async.shift();
        f && f();
        next();
    }, 10);
}

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();

Cải thiện từ phương thức của bạn 2. thay đổi từ var a = this.toFixed (chính xác) .split ('.'), Sang var Multipier = Math.pow (10, precision + 1), WholeNumber = Math.floor (this * bội số) ; var a = Math.round (WholeNumber / 10) * 10 / số nhân; if (Chuỗi (a) .indexOf ('.') <1) {a + = '.00'; } a = String (a) .split ('.'), Không sử dụng toFixed vì nó có lỗi.
vee

console.log (parseFloat ('4.835'). toFixed (2)); > 4.83 console.log (parseFloat ('54 .835 '). ToFixed (2)); > 54.84 console.log (parseFloat ('454.835'). ToFixed (2)); > 454.83 console.log (parseFloat ('8454.835'). ToFixed (2)); > 8454.83 tất cả số thập phân của giá trị này phải là .84 chứ không phải .83
vee


10

Một tùy chọn đơn giản cho vị trí dấu phẩy thích hợp bằng cách đảo ngược chuỗi đầu tiên và biểu thức chính quy.

String.prototype.reverse = function() {
    return this.split('').reverse().join('');
};

Number.prototype.toCurrency = function( round_decimal /*boolean*/ ) {       
     // format decimal or round to nearest integer
     var n = this.toFixed( round_decimal ? 0 : 2 );

     // convert to a string, add commas every 3 digits from left to right 
     // by reversing string
     return (n + '').reverse().replace( /(\d{3})(?=\d)/g, '$1,' ).reverse();
};

10

Tôi tìm thấy điều này từ: billing.js . Nó rất dễ dàng và hoàn toàn phù hợp với nhu cầu của tôi.

// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00

// European formatting (custom symbol and separators), can also use options object as second parameter:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99

// Negative values can be formatted nicely:
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

// Euro currency symbol to the right
accounting.formatMoney(5318008, {symbol: "€", precision: 2, thousand: ".", decimal : ",", format: "%v%s"}); // 1.008,00€ 


$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );- hiển thị 1.000,00 E
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.