วิธีการจัดรูปแบบตัวเลขเป็นสตริงสกุลเงินได้อย่างไร


1846

ฉันต้องการจัดรูปแบบราคาใน JavaScript ฉันต้องการฟังก์ชั่นที่รับfloatอาร์กิวเมนต์และคืนค่าการstringจัดรูปแบบดังนี้

"$ 2,500.00"

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?


8
ไม่มีฟังก์ชันformatNumberในตัวใน javascript
zerkms

500
โปรดไปยังทุกคนที่อ่านข้อความนี้ในอนาคตจะไม่ได้ใช้ลอยไปเป็นสกุลเงินเก็บ คุณจะสูญเสียความแม่นยำและข้อมูล คุณควรเก็บไว้เป็นจำนวนเต็มเซ็นต์ (หรือเพนนี ฯลฯ ) แล้วแปลงก่อนที่จะส่งออก
ฟิลิปทำเนียบขาว

8
@ user1308743 Float ไม่ได้เก็บตำแหน่งทศนิยม มันเก็บตัวเลขโดยใช้ค่าฐานและชดเชย 0.01 ไม่สามารถแทนได้จริง ดู: en.wikipedia.org/wiki/Floating_point#Accuracy_problems
ฟิลิปไวท์เฮ้าส์

6
@ user1308743: ลองนึกภาพคุณเป็นตัวแทนจำนวนมาก (สมมติว่าคุณเป็นคนที่โชคดีและเป็นยอดเงินในบัญชีธนาคารของคุณ) คุณต้องการที่จะสูญเสียเงินเพราะการขาดความแม่นยำหรือไม่?
ereOn

163
เหตุใดจึงไม่มีใครแนะนำสิ่งต่อไปนี้ (2500) .toLocaleString ("en-GB", {สไตล์: "สกุลเงิน", สกุลเงิน: "GBP", จำนวนขั้นต่ำในการขุด: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Nick Grealy

คำตอบ:


1792

Number.prototype.toFixed

โซลูชันนี้เข้ากันได้กับเบราว์เซอร์หลัก ๆ ทุกตัว:

  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)

เพียงคุณเพิ่มสัญลักษณ์สกุลเงิน (เช่น "$" + profits.toFixed(2) ) และคุณจะได้รับจำนวนเงินเป็นดอลลาร์

ฟังก์ชั่นที่กำหนดเอง

หากคุณต้องการใช้,ระหว่างแต่ละหลักคุณสามารถใช้ฟังก์ชั่นนี้:

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>

ใช้มันอย่างนั้น:

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

หากคุณจะใช้ '.' เสมอ และ ',' คุณสามารถปล่อยให้พวกเขาออกจากการโทรวิธีการของคุณและวิธีการจะเริ่มต้นพวกเขาสำหรับคุณ

(123456789.12345).formatMoney(2);

หากวัฒนธรรมของคุณมีสองสัญลักษณ์พลิก (เช่นชาวยุโรป) และคุณต้องการใช้ค่าเริ่มต้นเพียงวางเหนือสองบรรทัดต่อไปนี้ในformatMoneyวิธีการ:

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

ฟังก์ชั่นที่กำหนดเอง (ES6)

หากคุณสามารถใช้ไวยากรณ์ ECMAScript ที่ทันสมัย ​​(เช่นผ่าน Babel) คุณสามารถใช้ฟังก์ชันที่ง่ายกว่านี้แทน:

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
อย่างแรกสุดยอดรหัสที่รัดกุม อย่างไรก็ตามหากคุณเป็นคนอเมริกันคุณควรเปลี่ยนค่าเริ่มต้นdและtเป็น.และ,ตามลำดับเพื่อที่คุณจะได้ไม่ต้องระบุทุกครั้ง นอกจากนี้ฉันขอแนะนำให้แก้ไขจุดเริ่มต้นของreturnคำสั่งเพื่ออ่าน: return s + '$' + [rest]มิฉะนั้นคุณจะไม่ได้รับเครื่องหมายดอลลาร์
Jason

744
ไม่แน่ใจว่าทำไมคนคิดว่ารหัสนี้มีความสวยงาม มันอ่านไม่ออก ดูเหมือนว่าจะทำงานได้ดี แต่มันไม่สวยงาม
usr

86
ฟังก์ชั่น formatMoney นี้ถูกคัดลอกมาจากโค้ด JavaScript ขนาดเล็กบางอันใช่ไหม? คุณไม่สามารถโพสต์ต้นฉบับหรือไม่ ตัวแปร c, d, i, j, n, s และ t หมายถึงอะไร ตัดสินจากจำนวน upvotes และความคิดเห็นที่โพสต์นี้มีฉันสามารถสันนิษฐานได้ว่ารหัสนี้ได้ถูกคัดลอกไปวางในเว็บไซต์การผลิตทุกที่ ... ขอให้โชคดีในการรักษารหัสหากมีข้อผิดพลาดบางวัน!
zuallauz

259
"บทกวี"? เหมือนความสับสนมากขึ้น นี่ไม่ใช่โค้ดกอล์ฟ ใช้พื้นที่สีขาวเล็กน้อย ชื่อ var ที่เหมาะสมจะไม่เจ็บเช่นกัน
keithjgrant


1512

Intl.numberformat

Javascript มีตัวจัดรูปแบบตัวเลข (ส่วนหนึ่งของ Internationalization API)

// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
});

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

ซอ JS

ใช้undefinedแทนอาร์กิวเมนต์แรก ( 'en-US'ในตัวอย่าง) เพื่อใช้โลแคลระบบ (โลแคลผู้ใช้ในกรณีที่โค้ดกำลังทำงานอยู่ในเบราว์เซอร์)คำอธิบายเพิ่มเติมของรหัสสถานที่คำอธิบายเพิ่มเติมของรหัสสถาน

นี่คือ รายการของรหัสสกุลเงินรายการของรหัสสกุลเงิน

Intl.NumberFormat vs Number.prototype.toLocaleString

บันทึกสุดท้ายที่เปรียบเทียบสิ่งนี้กับรุ่นเก่า toLocaleString. พวกเขาทั้งสองมีฟังก์ชั่นเดียวกันเป็นหลัก อย่างไรก็ตาม toLocaleString ในสาขาที่เก่ากว่า (pre-Intl) ไม่รองรับสถานที่จริง : ใช้สถานที่ของระบบ ดังนั้นให้แน่ใจว่าคุณกำลังใช้รุ่นที่ถูกต้อง ( MDN แนะนำให้ตรวจสอบการมีอยู่ของIntl ) นอกจากนี้ประสิทธิภาพของทั้งสองอย่างก็เหมือนกันสำหรับรายการเดียวแต่ถ้าคุณมีตัวเลขจำนวนมากในการจัดรูปแบบการใช้Intl.NumberFormatจะเร็วกว่า ~ 70 เท่า นี่คือวิธีใช้toLocaleString:

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

หมายเหตุบางประการเกี่ยวกับการสนับสนุนเบราว์เซอร์

  • การสนับสนุนเบราว์เซอร์ไม่เป็นปัญหาอีกต่อไปในปัจจุบันด้วยการสนับสนุน 97.5% ทั่วโลก 98% ในสหรัฐอเมริกาและ 99% ในสหภาพยุโรป
  • มีshimให้การสนับสนุนบนเบราว์เซอร์ fossilized (เช่น IE8), ถ้าคุณต้องการจริงๆ
  • ดูCanIUseเพื่อดูข้อมูลเพิ่มเติม

89
JavaScript idomatic นี้โซลูชันที่เรียบง่ายและสง่างามเป็นสิ่งที่ฉันกำลังมองหา
Guilhem Soulas

9
การออกเสียงลงคะแนนอันนี้เพราะมันเป็นคำตอบที่ง่ายอย่างโง่เขลาที่ทำงานโดยกำเนิด
Trasiva

17
ค่อนข้างแน่ใจว่าเบราว์เซอร์ค่อนข้างสูงในขณะนี้รองรับ สิ่งนี้ควรได้รับการสนับสนุนมากกว่านี้
flq

2
นี่เป็นคำตอบที่ยอดเยี่ยมและฉันใช้มันทำงานกับค่าเงินแบบไดนามิกดังนั้นหากใช้ในยุโรปก็จะเปลี่ยนเป็น EUR และแสดงเครื่องหมายยูโร ทำงานได้ดี!
Sprose

3
มันคือปี 2018 และนี่ก็รองรับทุกที่ นี่ควรเป็นคำตอบที่ถูกต้อง
sarink

1340

วิธีแก้ปัญหาที่สั้นและเร็ว (ใช้ได้ทุกที่!)

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

'$&,'คิดที่อยู่เบื้องหลังการแก้ปัญหานี้ถูกใช้แทนที่ส่วนที่ตรงกับการแข่งขันครั้งแรกและจุลภาคคือ จับคู่จะทำโดยใช้วิธีการ lookahead คุณสามารถอ่านการแสดงออกเป็น"ตรงกับจำนวนถ้ามันจะตามด้วยลำดับสามชุดจำนวน (หนึ่งหรือมากกว่าหนึ่ง) และจุด"

แบบทดสอบ:

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/


วิธีแก้ปัญหาสั้น ๆ แบบขยาย

คุณยังสามารถขยายต้นแบบของNumberวัตถุเพื่อเพิ่มการรองรับเพิ่มเติมของจำนวนทศนิยมใด ๆ[0 .. n]และขนาดของกลุ่มตัวเลข[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/


วิธีแก้ปัญหาระยะสั้นแบบขยายสุดพิเศษ

ในเวอร์ชั่นขยายสุดคุณสามารถตั้งค่าตัวคั่นประเภทต่าง ๆ ได้:

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

ตัวอย่าง / การทดสอบ: http://jsfiddle.net/hAfMM/612/


21
จริง ๆ แล้วฉันก้าวไปอีกขั้นหนึ่ง: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,").
kalisjoshua

4
รุ่น CoffeeScript ที่มี VisioN & kalisjoshua regexp และวิธีการระบุตำแหน่งทศนิยม (เพื่อให้คุณสามารถกำหนดค่าเริ่มต้นเป็น 2 หรือระบุ 0 สำหรับไม่มีทศนิยม):Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Eric Anderson

11
@Abbas ใช่แทนที่\.ด้วย$(จุดสิ้นสุดของบรรทัด) this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,")คือ
VisioN

2
@hanumant ไวยากรณ์ทั่วไปค่อนข้างซับซ้อนที่นี่ดังนั้นฉันขอแนะนำให้คุณอ่านคู่มือเกี่ยวกับนิพจน์ทั่วไปก่อน (เช่นที่MDN ) $1,ความคิดที่อยู่เบื้องหลังมันถูกใช้แทนที่ส่วนที่ตรงกับการแข่งขันครั้งแรกและจุลภาคคือ จับคู่จะทำโดยใช้วิธีการ lookahead คุณสามารถอ่านการแสดงออกเป็น"ตรงกับจำนวนถ้ามันจะตามด้วยลำดับสามชุดจำนวน (หนึ่งหรือมากกว่าหนึ่ง) และจุด"
VisioN

2
@ JuliendePrabèreโปรดยกตัวอย่างตัวเลขที่ยาวซึ่งไม่สามารถใช้กับวิธีนี้ได้
VisioN

248

ลองดูที่วัตถุหมายเลข JavaScript และดูว่าสามารถช่วยคุณได้หรือไม่

  • toLocaleString() จะจัดรูปแบบตัวเลขโดยใช้ตัวคั่นหลักพันเฉพาะตำแหน่ง
  • toFixed() จะปัดเศษตัวเลขเป็นจำนวนทศนิยมเฉพาะ

หากต้องการใช้สิ่งเหล่านี้ในเวลาเดียวกันค่าจะต้องมีการเปลี่ยนชนิดของตัวเลขกลับไปเป็นตัวเลขเพราะทั้งคู่จะส่งออกสตริง

ตัวอย่าง:

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

2
ขอบคุณ! จากความคิดนี้ฉันสามารถทำให้มันสั้นและเรียบง่ายพอ! (และเป็นภาษาท้องถิ่น) ยอดเยี่ยม
Daniel Magliola

7
ที่จริงคุณสามารถ เช่นสำหรับดอลลาร์: '$' + (ค่า + 0.001) .toLocaleString (). ชิ้น (0, -1)
Zaptree

6
ดูเหมือนว่าจะดี แต่มีการสนับสนุนเบราว์เซอร์น้อยในขณะนี้
acorncom

1
@acorncom ทำไมคุณถึงบอกว่ามี "การสนับสนุนเบราว์เซอร์น้อย"? วัตถุ Number มีมาตั้งแต่ Javascript 1.1 โปรดให้ข้อมูลอ้างอิงที่สำรองการอ้างสิทธิ์ของคุณ
Doug S

2
ควรใช้ความระมัดระวังว่ามีรุ่นเก่าtoLocaleStringที่ใช้ระบบภาษาและใหม่ (เข้ากันไม่ได้) ที่มาจาก ECMAScript Intl API อธิบายที่นี่ คำตอบนี้ดูเหมือนจะมีไว้สำหรับรุ่นเก่า
Aross

162

ด้านล่างนี้คือรหัสPatrick Desjardins (นามแฝง Daok)พร้อมความเห็นเล็กน้อยและการเปลี่ยนแปลงเล็กน้อย:

/* 
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) : ''); 
}

และนี่คือการทดสอบบางส่วน:

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

การเปลี่ยนแปลงเล็กน้อยคือ:

  1. ย้ายบิตที่จะทำเฉพาะเมื่อไม่ได้เป็นMath.abs(decimals)NaN

  2. decimal_sep ต้องไม่เป็นสตริงว่างอีกต่อไป (ตัวแยกทศนิยมบางประเภทต้องมี)

  3. เราใช้typeof thousands_sep === 'undefined'ตามที่แนะนำในวิธีที่ดีที่สุดในการพิจารณาว่าอาร์กิวเมนต์ไม่ได้ถูกส่งไปยังฟังก์ชัน JavaScript

  4. (+n || 0)ไม่จำเป็นเพราะthisเป็นNumberวัตถุ

JS Fiddle


8
คุณอาจต้องการใช้ '10' เป็นค่าฐานใน parseInt มิฉะนั้นหมายเลขใด ๆ ที่ขึ้นต้นด้วย '0' จะใช้เลขฐานแปด
sohtimsso1970

3
@ sohtimsso1970: ขอโทษที่ตอบช้า แต่คุณช่วยอธิบายเพิ่มเติมได้ไหม? ฉันไม่เห็นว่าหมายเลขใดสามารถตีความได้ว่าเป็นเลขฐานแปด parseIntถูกเรียกบนค่าสัมบูรณ์ของจำนวนเต็มส่วนของจำนวน ส่วนที่ INTEGER ไม่สามารถเริ่มต้นด้วย ZERO เว้นแต่ว่ามันจะเป็นแค่ ZERO! และparseInt(0) === 0อาจเป็นฐานแปดหรือทศนิยม
Marco Demaio

ลองตัวอย่างเช่น: parseInt ("016") ... ส่งคืน 14 เนื่องจาก parseInt ถือว่าเป็นรหัสแปดเมื่อสตริงเริ่มต้นด้วยศูนย์
Tracker1

4
@ Tracker1: ผมเข้าใจว่าเป็นจำนวนที่เริ่มต้นด้วยถือว่าเป็นฐานแปดโดย0 parseIntแต่ในรหัสนี้เป็นไปไม่ได้ที่parseIntจะรับ016เป็นอินพุต (หรือค่าที่จัดรูปแบบฐานแปดอื่น ๆ ) เพราะอาร์กิวเมนต์ที่ส่งผ่านไปยังparseIntถูกประมวลผลครั้งที่ 1 โดยMath.absฟังก์ชั่น ดังนั้นจึงไม่มีวิธีparseIntรับหมายเลขที่ขึ้นต้นด้วยศูนย์เว้นแต่ว่าจะเป็นเพียงศูนย์หรือ0.nn(ที่nnเป็นทศนิยม) แต่ทั้งสอง0และ0.nnสตริงจะถูกแปลงparseIntเป็นศูนย์ธรรมดาตามที่ควรจะเป็น
Marco Demaio

ฟังก์ชั่นนี้ไม่ถูกต้อง:> (2030) .toMoney (0, '.', ''); <"2 03 0"
Anton P Robul

124

accounting.jsเป็นไลบรารี JavaScript ขนาดเล็กสำหรับการจัดรูปแบบตัวเลขเงินและสกุลเงิน


... เพียงจำไว้ว่าต้องส่งสัญลักษณ์สกุลเงินมิฉะนั้นจะเกิดข้อผิดพลาดใน IE7 และ IE8, IE9 ใช้ได้ทั้งสองวิธี
vector

2
ดูเหมือนว่าข้อผิดพลาด IE7 / IE8 ได้รับการแก้ไข
Mat Schaffer

2
นี้เป็นห้องสมุดที่ดีความสามารถในการส่งผ่านสัญลักษณ์สกุลเงินจะยังเป็นความคิดที่ดีเนื่องจากทุกรายละเอียดที่สกุลเงินที่มีอยู่ในซิงเกิ้ลฟังก์ชั่นการโทร / การตั้งค่า
farinspace

2
ฉันชอบความจริงที่ว่าคุณสามารถย้อนกลับได้ - ส่งสตริงสกุลเงินที่จัดรูปแบบแล้วและรับค่าตัวเลข
Neil Monroe

2
accounting.js ดูเหมือนจะไม่ได้รับการบำรุงรักษาเมื่อเร็ว ๆ นี้ หนึ่งทางแยกที่มีการเปลี่ยนแปลงล่าสุดคือgithub.com/nashdot/accounting-js
RationalDev ชอบ GoFundMonica

124

ถ้าจำนวนเป็นตัวเลขให้พูด-123ออกมา

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

จะผลิตสตริง "-$123.00"จะผลิตสตริง

นี่คือการทำงานที่สมบูรณ์ตัวอย่างเช่น


7
คำตอบนี้เกือบจะอยู่ที่นั่นแล้ว แต่ฉันต้องการให้ปัดเศษเป็นเงินที่ใกล้ที่สุด นี่คือสิ่งที่ฉันใช้เป็นจำนวนเงิน ToLocaleString ('en-GB', {style: 'currency', สกุลเงิน: 'GBP', maximumFractionDigits: 2});
นิโก้

รหัสด้านบนจะปัดเศษตามจำนวนหลักที่คุณต้องการ ดูตัวอย่างและพิมพ์ 1.237 ในกล่องอินพุต
Daniel Barbalace

3
ดูเหมือนจะไม่ทำงานใน Safari มันจะคืนค่าตัวเลขเป็นสตริงโดยไม่มีการจัดรูปแบบใด ๆ
Lance Anderson

1
ว้าวนี่เป็นคำตอบที่ยอดเยี่ยมจริงๆ ควรอยู่ด้านบน
อีธาน

2
หากด้วยเหตุผลบางอย่างที่คุณไม่ต้องการเซ็นต์คุณสามารถเปลี่ยนความแม่นยำทศนิยมด้วย:minimumFractionDigits: 0
Horacio

99

นี่คือฟอร์แมต js money ที่ดีที่สุดที่ฉันเคยเห็น:

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

มีการจัดรูปแบบใหม่และยืมมาจากที่นี่: https://stackoverflow.com/a/149099/751484

คุณจะต้องระบุผู้ออกแบบสกุลเงินของคุณเอง (คุณใช้ $ ด้านบน)

เรียกว่าเป็นแบบนี้ (แม้ว่าโปรดทราบว่า args มีค่าเริ่มต้นเป็น 2, เครื่องหมายจุลภาคและระยะเวลาดังนั้นคุณไม่จำเป็นต้องระบุ args ใด ๆ หากเป็นการตั้งค่าของคุณ):

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

ระวังสัญญาณ globals, i, j
hacklikecrack

6
@hacklikecrack ตัวแปรทั้งหมดเป็นโลคอล พวกเขาอยู่ในvarคำสั่ง
Jonathan M

3
ขออภัยใช่แม้ว่าคุณจะประกาศการขัดแย้งซ้ำ เยื้อง! ;)
hacklikecrack

การใช้ชื่อตัวแปรที่น่ากลัว!
Serj Sagan

77

มีคำตอบที่ดีอยู่แล้วที่นี่ นี่เป็นอีกความพยายามเพื่อความสนุก:

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

และการทดสอบบางอย่าง:

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

แก้ไข: ตอนนี้มันจะจัดการกับจำนวนลบเช่นกัน


บทกวี สุกใส คุณได้ลองใช้ lessRight () developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ซึ่งควรกำจัด reverse () หรือไม่
Steve

1
@Steve - ถูกต้อง แต่คุณต้องทำสิ่งที่ต้องการi = orig.length - i - 1ในการติดต่อกลับ ถึงกระนั้นการสำรวจเส้นทางที่น้อยลงของอาเรย์
เวย์น

11
ไม่เกี่ยวกับความเข้ากันได้: reduceวิธีการนี้ได้รับการแนะนำใน Ecmascript 1.8 และไม่ได้รับการสนับสนุนใน Internet Explorer 8 และต่ำกว่า
Blaise

เช่น @Blaise กล่าวว่าวิธีนี้จะไม่ทำงานใน IE 8 หรือต่ำกว่า
rsbarro

ใช่ว่าถูกต้องแน่นอน ดังที่ระบุไว้ในคำตอบของตัวเองนี่เป็นเพียงเพื่อความสนุกสนาน นอกจากนี้ควรจัดการกับจำนวนลบได้ดี
Wayne

76

ใช้งานได้กับเบราว์เซอร์ปัจจุบันทั้งหมด

ใช้toLocaleStringเพื่อจัดรูปแบบสกุลเงินในรูปแบบที่ไวต่อภาษา (โดยใช้รหัสสกุลเงินISO 4217 )

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

ตัวอย่างตัวอย่างโค้ดแรนด์แอฟริกาใต้สำหรับ @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
เนื่องจากอาร์กิวเมนต์ "โลแคล" และ "ตัวเลือก" ได้รับการสนับสนุนโดยเบราว์เซอร์จำนวนน้อยมากเช่น Chrome 24, IE11 และ Opera 15 Firefox, Safari และเวอร์ชันอื่น ๆ ที่เก่ากว่ายังไม่รองรับ
VisioN

3
ตกลงว่ามันไม่ได้รับการสนับสนุนอย่างเต็มที่ในทุกเบราว์เซอร์ (ยัง) แต่ก็ยังคงเป็นทางออก (และเป็นโซลูชันที่ถูกต้องที่สุดเนื่องจากรองรับการทำงานกับเบราว์เซอร์ที่ไม่รองรับและเป็นคุณลักษณะที่มีเอกสารของ Javascript API)
Nick Grealy

1
ฉันชอบสิ่งนี้และมีความสุขที่ทำงานกับการจัดกลุ่มตัวเลขแบบอินเดีย
MSC

7
สิ่งนี้ได้รับการสนับสนุนอย่างเต็มที่ตั้งแต่ปี 2017 และควรเป็นคำตอบที่ถูกต้องเท่านั้น
Evgeny

1
ล่าสุดและยิ่งใหญ่ที่สุด :) FF69, Chrome76 ฯลฯ "R 2 500,00" ไม่ใช่สิ่งที่เราใช้ที่นี่ควรเป็น "R 2,500.00" เหมือนกับ en-GB
avenmore

70

ฉันคิดว่าสิ่งที่คุณต้องการคือ f.nettotal.value = "$" + showValue.toFixed(2);


@ บดขยี้งานนี้ แต่ไม่นำการคำนวณไปยังเขตข้อมูลภาษีอีกต่อไป
Rocco The Taco

11
เมื่อคุณต่อท้ายเครื่องหมาย $ จะไม่มีหมายเลข แต่เป็นสตริงอีกต่อไป
บดขยี้

ตัวเลือกนี้ไม่ใส่เครื่องหมายจุลภาคระหว่างหลักพัน :-(
Simon East

29

Numeral.js - ไลบรารี js สำหรับการจัดรูปแบบตัวเลขอย่างง่ายโดย @adamwdraper

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"

ดูเหมือนว่าส้อม Numbro จะได้รับความรักมากขึ้นในขณะที่ Numeral.js ดูเหมือนจะถูกทอดทิ้ง: github.com/foretagsplatsen/numbro
RationalDev ชอบ GoFundMonica

Numeral.js เปิดใช้งานอีกครั้ง
adamwdraper

27

ตกลงตามสิ่งที่คุณพูดฉันใช้สิ่งนี้:

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;

ฉันเปิดให้คำแนะนำในการปรับปรุง (ฉันไม่ต้องการรวม YUI เพื่อทำสิ่งนี้ :-)) ฉันรู้แล้วว่าฉันควรจะตรวจจับ "" แทนที่จะใช้มันเป็นตัวแยกทศนิยม ...


8
โปรดทราบว่ารุ่นของคุณไม่ถูกต้องเป็นทศนิยมสองหลัก ตัวอย่างเช่น 3.706 จะจัดรูปแบบเป็น "£ 3.70" ไม่ใช่ "£ 3.71" อย่างที่ควรจะเป็น
Ates Goral

ใช่มันไม่เป็นไรในกรณีของฉันเนื่องจากจำนวนเงินที่ฉันทำงานด้วยมีตัวเลขมากที่สุด 2 หลักเหตุผลที่ฉันต้องแก้ไขเป็น 2 ทศนิยมสำหรับจำนวนที่ไม่มีทศนิยมหรือมีเพียง 1
Daniel Magliola

26

ฉันใช้ไลบรารีGlobalize (จาก Microsoft):

มันเป็นโครงการที่ยอดเยี่ยมในการแปลตัวเลขสกุลเงินและวันที่และให้พวกเขาจัดรูปแบบที่ถูกต้องโดยอัตโนมัติตามที่ตั้งของผู้ใช้! ... และแม้ว่ามันควรจะเป็นส่วนขยาย jQuery แต่ปัจจุบันเป็นห้องสมุดอิสระ 100% ฉันขอแนะนำให้คุณลองใช้ดู! :)


3
ว้าวทำไมถึงไม่เพิ่มจำนวนขึ้นอีก? ไลบรารีมาตรฐานขนาดใหญ่สำหรับการจัดรูปแบบทุกประเภท พารามิเตอร์การจัดรูปแบบมาตรฐานอุตสาหกรรมพร้อมโลกาภิวัตน์ที่ถูกต้อง คำตอบที่ดี !!
pbarranis

มันยังถือว่าเป็นระยะอัลฟาดังนั้นใช้ความระมัดระวัง แต่การค้นหาที่ดี
Neil Monroe

1
ไม่อยู่ในอัลฟ่า (หรือเบต้า) อีกต่อไป สิ่งนี้ดูเหมือนจะมีประโยชน์มากในขณะที่เรารอให้ Safari ได้มาตรฐานใหม่และ IE <11 จะตาย
Guy Schalnat

25

javascript-number-formatter (ก่อนหน้านี้ที่Google Code )

  • สั้น, รวดเร็ว, ยืดหยุ่น แต่สแตนด์อโลน เพียง 75 บรรทัดรวมถึงข้อมูลใบอนุญาต MIT, บรรทัดว่างและความคิดเห็น
  • ยอมรับการจัดรูปแบบตัวเลขมาตรฐานเช่นหรือปฏิเสธ#,##0.00-000.####
  • ยอมรับรูปแบบใด ๆ เช่นประเทศ# ##0,00, #,###.##, #'###.##หรือประเภทของสัญลักษณ์ที่ไม่ใช่เลขใด ๆ
  • ยอมรับการจัดกลุ่มตัวเลขจำนวนเท่าใดก็ได้ #,##,#0.000หรือ#,###0.##ถูกต้องทั้งหมด
  • ยอมรับการจัดรูปแบบที่ซ้ำซ้อน / การป้องกันที่เข้าใจผิด ##,###,##.#หรือ0#,#00#.###0#ตกลงทั้งหมด
  • การปัดเศษตัวเลขอัตโนมัติ
  • format( "0.0000", 3.141592)อินเตอร์เฟซที่เรียบง่ายหน้ากากอุปทานเพียงและคุ้มค่าเช่นนี้
  • รวมคำนำหน้า & คำต่อท้ายด้วยมาสก์

(ข้อความที่ตัดตอนมาจาก README)


23

+1 ถึง Jonathan M เพื่อให้วิธีการดั้งเดิม เนื่องจากนี่เป็นตัวจัดรูปแบบสกุลเงินอย่างชัดเจนฉันจึงไปข้างหน้าและเพิ่มสัญลักษณ์สกุลเงิน (ค่าเริ่มต้นเป็น '$') ไปยังเอาท์พุทและเพิ่มเครื่องหมายจุลภาคเริ่มต้นเป็นตัวคั่นหลักพัน หากคุณไม่ต้องการสัญลักษณ์สกุลเงิน (หรือตัวคั่นหลักพัน) ให้ใช้ "" (สตริงว่าง) เป็นอาร์กิวเมนต์ของคุณ

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 แรกเป็นสิ่งที่แปลกเนื่องจากตัวแปรเหล่านั้นถูกประกาศในการประกาศฟังก์ชันแล้ว นอกเหนือจากนั้นขอบคุณ!
Rich Bradshaw

2
คุณถูก. นั่นเป็นข้อผิดพลาดที่ฉันนำมาจากต้นฉบับของ Jonathan M ซึ่งพวกเขาทั้งหมดถูกล่ามโซ่ไว้ในรูปแบบวาร์เดียว สิ่งเหล่านั้นควรได้รับมอบหมายอย่างง่าย แก้ไข
XML

สำหรับเรื่องนั้นฉันคิดว่านี่อาจจะปรับให้เหมาะสมก่อนกำหนดและควรได้รับการปรับโครงสร้างใหม่เพื่อให้สามารถอ่านได้ แต่เป้าหมายของฉันคือการเพิ่มรหัสของ OP ไม่ใช่การแก้ไขโดยพื้นฐาน
XML

มันไม่ได้เลวร้ายเกินไป - +n || 0เป็นสิ่งเดียวที่ดูเหมือนแปลก ๆ เล็กน้อย (สำหรับฉันแล้ว)
Rich Bradshaw

2
thisเป็นชื่อตัวแปรที่มีประโยชน์อย่างสมบูรณ์ การแปลงเพื่อnให้คุณสามารถบันทึก 3 ตัวอักษรในเวลาที่กำหนดอาจมีความจำเป็นในยุคที่ RAM และแบนด์วิดธ์ถูกนับเป็น KB แต่เป็นเพียงความงงงวยในยุคที่ minifier จะดูแลทุกอย่างก่อนที่จะตีการผลิต การเพิ่มประสิทธิภาพขนาดเล็กที่ชาญฉลาดอื่น ๆ เป็นที่ถกเถียงกันอย่างน้อย
XML

22

มีพอร์ตจาวาสคริปต์ของฟังก์ชั่น PHP "number_format"

ฉันคิดว่ามันมีประโยชน์มากเพราะใช้งานง่ายและเป็นที่จดจำสำหรับนักพัฒนา 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; 
}

(บล็อกความคิดเห็นจากต้นฉบับรวมอยู่ด้านล่างสำหรับตัวอย่างและเครดิตเมื่อถึงกำหนด)

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

นี่เป็นเพียงฟังก์ชั่นที่ถูกต้องเพียงอย่างเดียว:> number_format (2030, 0, '.', '' ') <' 2 030 'เยี่ยมมาก! ขอบคุณ
Anton P Robul

21

วิธีที่สั้นกว่า (สำหรับการแทรกพื้นที่เครื่องหมายจุลภาคหรือจุด) ด้วยการแสดงออกปกติ?

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

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

20

ไม่เห็นอะไรแบบนี้ ค่อนข้างกระชับและเข้าใจง่าย

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

นี่คือรุ่นที่มีตัวเลือกเพิ่มเติมในผลลัพธ์สุดท้ายเพื่อให้สามารถจัดรูปแบบสกุลเงินต่าง ๆ ในรูปแบบท้องถิ่นที่แตกต่างกัน

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


ข้อมูลโค้ดที่ยอดเยี่ยมขอบคุณ อย่างไรก็ตามโปรดระวังเนื่องจากจะไม่ทำงานบน IE เนื่องจากไม่รองรับพารามิเตอร์เริ่มต้นและ "const" และ "let" ไม่รองรับใน <IE11 ใช้สิ่งนี้เพื่อแก้ไข: + moneyFormat: ฟังก์ชัน (ราคา, เครื่องหมาย) {+ if (! sign) sign = '$'; + pieces = parseFloat (ราคา) .toFixed (2) .split ('') + var ii = pieces.length - 3
Charlie Dalsass

ไม่ต้องกังวล @CharlieDalsass ฉันอยากจะแนะนำให้ใช้ Babel เพื่อรวบรวมลงใน ES5 สำหรับรหัสการผลิต
synthet1c

แต่จะทำอย่างไรกับสกุลเงินยูโร 1.000,00 ยูโร

@YumYumYum ฉันได้เพิ่มตัวอย่างแบบเต็มพร้อมตัวเลือกการจัดรูปแบบเพิ่มเติมเพื่อให้มีความยืดหยุ่นมากขึ้น
synthet1c

18

คำตอบของPatrick Desjardinsดูดี แต่ฉันชอบจาวาสคริปต์ของฉันง่าย นี่คือฟังก์ชั่นที่ฉันเพิ่งเขียนเพื่อใช้ตัวเลขและส่งกลับในรูปแบบสกุลเงิน (ลบเครื่องหมายดอลลาร์)

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

ฉันต้องการบางสิ่งบางอย่างในการทำงานทั้งในเบราว์เซอร์และในโหนดรุ่นเก่า มันทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ
n8jadams

17

ส่วนหลักคือการแทรกตัวคั่นหลักพันซึ่งสามารถทำได้ดังนี้:

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

ฉันได้รับตัวเลขที่ไม่ถูกต้องขณะป้อนค่าลบไปที่ ins1000Sep ()
ปีเตอร์

16

มีการfunction แก้ไขไว้ภายในแล้วjavascript

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

คำตอบนี้ดูเหมือนซ้ำซ้อน ความสนใจของคำตอบถูกระบุแล้วtoFixed()
เอียนดันน์

3
toFixed()เป็นฟังก์ชั่นของNumberวัตถุและจะไม่ทำงานvar numถ้ามันเป็นStringดังนั้นบริบทเพิ่มเติมช่วยฉัน
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;
}

จากWillMaster


ขนาดเล็กและเรียบง่าย ขอบคุณ.
Connor Simpson

1
เรียบง่าย แต่ไม่มีเครื่องหมายจุลภาคสำหรับ 1,000
aron

15

ฉันแนะนำคลาส NumberFormat จาก Google API การแสดง

คุณสามารถทำสิ่งนี้:

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

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

ฉันหวังว่ามันจะช่วย


14

นี่อาจจะสายไปซักหน่อย แต่นี่เป็นวิธีที่ฉันเพิ่งทำเพื่อเพื่อนร่วมงานเพื่อเพิ่ม.toCurrencyString()ฟังก์ชั่นที่รับรู้ในท้องถิ่นให้กับตัวเลขทั้งหมด การปรับภายในใช้สำหรับการจัดกลุ่มตัวเลขเท่านั้นไม่ใช่เครื่องหมายสกุลเงิน - หากคุณกำลังส่งออกดอลลาร์ใช้"$"ตามที่ระบุเนื่องจาก$123 4567ในญี่ปุ่นหรือจีนมีจำนวน USD เท่ากันกับ$1,234,567ที่นี่ในสหรัฐอเมริกา หากคุณกำลังส่งออกยูโร / ฯลฯ ให้เปลี่ยนเครื่องหมายสกุลเงิน"$"แล้วเปลี่ยนเครื่องหมายสกุลเงินจาก

ประกาศสิ่งนี้ในหัวของคุณหรือที่ใดก็ตามที่จำเป็นก่อนที่คุณจะต้องใช้มัน:

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

ถ้าอย่างนั้นคุณก็ทำได้! ใช้(number).toCurrencyString()ที่ใดก็ได้ที่คุณต้องการส่งออกจำนวนเป็นสกุลเงิน

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

12

ตามปกติมีหลายวิธีในการทำสิ่งเดียวกัน แต่ฉันจะหลีกเลี่ยงการใช้ Number.prototype.toLocaleStringเพราะสามารถคืนค่าที่แตกต่างกันตามการตั้งค่าผู้ใช้

ฉันยังไม่แนะนำให้ขยาย Number.prototype - ต้นแบบดั้งเดิมของวัตถุส่วนขยายเป็นวิธีปฏิบัติที่ไม่ถูกต้องเนื่องจากมันอาจทำให้เกิดความขัดแย้งกับโค้ดของคนอื่น ๆ (เช่นไลบรารี / กรอบ / ปลั๊กอิน) และอาจเข้ากันไม่ได้กับการใช้งาน / รุ่น JavaScript ในอนาคต

ฉันเชื่อว่านิพจน์ทั่วไปเป็นวิธีที่ดีที่สุดสำหรับปัญหานี่คือการดำเนินการของฉัน:

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

แก้ไขเมื่อ 2010/08/30: เพิ่มตัวเลือกในการตั้งค่าจำนวนหลักทศนิยม แก้ไขเมื่อ 2011/08/23: เพิ่มตัวเลือกในการตั้งค่าตัวเลขทศนิยมให้เป็นศูนย์


จุดของ toLocaleString ก็คือมันจะปรับด้วยการตั้งค่าของผู้ใช้
โจเซฟเลนน็อกซ์

11

ต่อไปนี้เป็นวิธีแก้ไขทั้งหมดผ่านชุดทดสอบชุดทดสอบและเกณฑ์มาตรฐานหากคุณต้องการคัดลอกและวางเพื่อทดสอบลองใช้สรุปสาระสำคัญนี้

วิธีที่ 0 (RegExp)

ขึ้นอยู่กับhttps://stackoverflow.com/a/14428340/1877620แต่แก้ไขหากไม่มีจุดทศนิยม

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

วิธีที่ 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('.');
    };
}

วิธีที่ 2 (แบ่งเป็นอาร์เรย์)

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

วิธีที่ 3 (วน)

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

ตัวอย่างการใช้งาน

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

เครื่องสกัด

หากเราต้องการตัวคั่นหลักพันที่กำหนดเองหรือตัวแยกทศนิยมให้ใช้replace():

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

ชุดทดสอบ

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

เกณฑ์มาตรฐาน

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

ปรับปรุงจากวิธีการของคุณ 2. เปลี่ยนจาก var a = this.toFixed (ความแม่นยำ) .split ('.') เป็น var multipier = Math.pow (10, ความแม่นยำ + 1), wholeNumber = Math.floor (ตัวคูณ * นี้) ; var a = Math.round (wholeNumber / 10) * 10 / ตัวคูณ; if (String (a) .indexOf ('.') <1) {a + = '.00'; } a = String (a) .split ('.'), อย่าใช้ toFixed เพราะมันเป็นบั๊กกี้
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 ทศนิยมทั้งหมดของค่าเหล่านี้ควรเป็น. 84 ไม่ใช่. 83
vee


10

ตัวเลือกง่าย ๆ สำหรับการวางคอมม่าที่เหมาะสมโดยการย้อนกลับสตริงแรกและ regexp ขั้นพื้นฐาน

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

ฉันพบนี้จาก: accounting.js มันง่ายมากและลงตัวกับความต้องการของฉัน

// 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" } ) );- แสดง 1.000,00 E
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.