วิธีพิมพ์ตัวเลขด้วยเครื่องหมายจุลภาคเป็นตัวคั่นหลักพันใน JavaScript


1781

ฉันพยายามพิมพ์จำนวนเต็มในJavaScriptด้วยเครื่องหมายจุลภาคเป็นตัวคั่นหลักพัน ตัวอย่างเช่นฉันต้องการแสดงหมายเลข 1234567 เป็น "1,234,567" ฉันจะทำสิ่งนี้อย่างไร

นี่คือวิธีที่ฉันทำ:

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

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


156
Number (x) .toLocaleString ()
Boffin

@Boffin สิ่งนี้ไม่ทำงานสำหรับหมายเลขประเภทการป้อนข้อมูล (เนื่องจากเครื่องหมายจุลภาค) - ในคำตอบที่ยอมรับเราสามารถแทนที่เครื่องหมายจุลภาคเป็นจุดและหมายเลขประเภทการป้อนข้อมูลจะทำงาน
Vitaly Zdanevich

48
ที่น่าสังเกตว่าNumber.prototype.toLocaleString ยังไม่ได้ทำงานใน Safari ใน2016 แทนที่จะทำการฟอร์แมตตัวเลขมันแค่คืนค่าไม่มีข้อผิดพลาด การมี facepalm ที่ใหญ่ที่สุดในวันนี้เป็นผลมาจากสิ่งนั้น ... #goodworkApple
aendrew

อย่างไรก็ตามดูเหมือนว่าจะใช้งานได้ใน iOS Safari
ทิม

toLocaleString ไม่สอดคล้องกันและไม่ควรใช้ ตัวอย่างเช่น - บน Firefox สิ่งนี้จะคืน 1,234 แต่สำหรับ IE สิ่งนี้จะเพิ่มทศนิยม: 1,234.00
Bort

คำตอบ:


2832

ฉันใช้ความคิดจากคำตอบของ Kerry แต่ทำให้มันง่ายขึ้นเพราะฉันแค่มองหาบางสิ่งที่ง่ายสำหรับจุดประสงค์เฉพาะของฉัน นี่คือสิ่งที่ฉันทำ:

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


regex ใช้การยืนยันแบบ lookahead 2 ครั้ง:

  • ค่าบวกเพื่อค้นหาจุดใด ๆ ในสตริงที่มีหลายหลัก 3 ตัวในแถวถัดไป
  • การยืนยันเชิงลบเพื่อให้แน่ใจว่าจุดนั้นมีหลายหลัก 3 หลักเท่านั้น การแสดงออกแทนทำให้เครื่องหมายจุลภาคที่นั่น

ตัวอย่างเช่นหากคุณผ่าน123456789.01การยืนยันเชิงบวกจะจับคู่ทุกจุดทางด้านซ้ายของ 7 (เนื่องจาก789มีหลายหลัก 3 หลัก678คือคูณ 3 หลัก567ฯลฯ ) ตรวจสอบเชิงลบยืนยันว่าหลาย 3 หลักไม่ได้มีตัวเลขใด ๆ หลังจากที่มัน 789มีระยะเวลาหลังจากนั้นจึงเป็นจำนวนเต็ม 3 หลักดังนั้นเครื่องหมายจุลภาคจึงไปที่นั่น 678เป็นตัวเลขสามหลัก แต่มี9หลังดังนั้นตัวเลข 3 หลักเหล่านั้นเป็นส่วนหนึ่งของกลุ่ม 4 และเครื่องหมายจุลภาคไม่ได้ไปที่นั่น 567ในทำนองเดียวกันสำหรับ 456789คือ 6 หลักซึ่งเป็นผลคูณของ 3 ดังนั้นเครื่องหมายคอมม่าจะอยู่ก่อนหน้านั้น 345678คือผลคูณของ 3 แต่มันมีค่า9หลังจากนั้นดังนั้นไม่มีเครื่องหมายจุลภาค และอื่น ๆ \B ป้องกันไม่ให้ regex ใส่เครื่องหมายจุลภาคที่จุดเริ่มต้นของสตริง

@ neu-rahพูดถึงว่าฟังก์ชั่นนี้จะเพิ่มจุลภาคในสถานที่ที่ไม่พึงประสงค์หากมีตัวเลขมากกว่า 3 หลักหลังจุดทศนิยม หากนี่เป็นปัญหาคุณสามารถใช้ฟังก์ชั่นนี้:

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

@ tjcrowderชี้ให้เห็นว่าขณะนี้ JavaScript มี lookbehind ( ข้อมูลสนับสนุน ) ก็สามารถแก้ไขได้ในการแสดงออกปกติตัวเอง:

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

(?<!\.\d*)เป็นลักษณะเชิงลบที่ระบุว่าการแข่งขันไม่สามารถนำหน้าด้วย.ตัวเลขศูนย์หรือมากกว่า มุมมองเชิงลบนั้นเร็วกว่าsplitและjoinวิธีแก้ปัญหา ( การเปรียบเทียบ ) อย่างน้อยใน V8


21
เจ๋งมากสังเกตว่ามีปัญหากับตัวเลขที่มีมากกว่า 3 ตำแหน่งหลังจุดทศนิยม
Eric Petroelje

60
ลอง numberWithCommas (12345.6789) -> "12,345.6,789" ฉันไม่ชอบมัน
neu-rah

4
มันใช้งานไม่ได้กับเศษส่วนเราไม่ต้องการคอม
Mugen

30
การปรับปรุงเล็กน้อยที่แก้ไขหลังจาก '.' ปัญหา '123456789.01234'.replace (/ \ B (? = (? = \ d * \.) (\ d {3}) + (?! \ d)) / g,' _ ')
Dmitrij Golubev

8
@DmitrijGolubev ไม่ทำงานกับจำนวนเต็ม บางทีการบังคับให้จุดทศนิยมเป็นทางออก

1809

ฉันไม่มีใครแปลกใจที่กล่าวถึงNumber.prototype.toLocaleString มันนำมาใช้ใน JavaScript 1.5 (ซึ่งเปิดตัวในปี 1999) ดังนั้นโดยทั่วไปจึงรองรับเบราว์เซอร์หลัก

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

นอกจากนี้ยังทำงานใน Node.js ณ v0.12 ผ่านการรวมของIntl

เพียงแค่ให้ความสนใจว่าฟังก์ชันนี้คืนค่าสตริงไม่ใช่ตัวเลข

หากคุณต้องการสิ่งที่แตกต่างNumeral.jsอาจน่าสนใจ


17
@csigrist คะแนนที่ดี แต่ก็ไม่ได้เลวร้ายอย่างที่เห็น ความเร็วเป็นเบราว์เซอร์ขึ้น ใน FF หรือ Opera มันทำงานได้ดี ฉันใช้ Chrome ในการดูด สำหรับศูนย์: var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00"ตัวเลือกเหล่านั้นไม่ทำงานใน FF หรือ Safari
uKolka

22
ความแตกต่างของประสิทธิภาพอาจมีหรือไม่มีปัญหาขึ้นอยู่กับบริบท หากใช้กับผลการค้นหาจำนวน 1,000 ตารางผลลัพธ์จะมีความสำคัญมากกว่า แต่หากใช้เพียงค่าเดียวความแตกต่างนั้นเล็กน้อย แต่ข้อดีก็คือว่ามันเป็นที่รู้จักสถานที่เพื่อให้คนในยุโรปจะเห็น34.523.453,345หรือ34 523 453345 สิ่งนี้จะมีความสำคัญมากขึ้นในไซต์ที่มีผู้เข้าชมจากหลายประเทศ
T Nguyen

6
น่ากลัว ในที่สุดคำตอบด้วยฟังก์ชั่นพื้นเมือง และยิ่งไปกว่านั้นอันนี้แสดงอย่างถูกต้องในประเทศต่าง ๆ ที่มีตัวคั่นที่แตกต่างกัน (ในสาธารณรัฐเช็กที่เราเขียนX XXX XXX,YYY)
Tomáš Zato - Reinstate Monica

22
การปรับปรุงสำหรับชาว Google: toLocaleStringทำงานใน Node.js ณ v0.12 ผ่านการรวมของสนามบินนานาชาติ
srobinson

8
@MSC คุณควรลองparseInt("1234567", 10).toLocaleString('en-US', {minimumFractionDigits: 2})หรือnew Number("1234567").toLocaleString('en-US', {minimumFractionDigits: 2})แทน มันไม่ทำงานเพราะคุณใช้มันในสตริงไม่ใช่ตัวเลข
uKolka

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

⚠โปรดทราบว่าจาวาสคริปต์นั้นมีค่าจำนวนเต็มสูงสุดเท่ากับ9007199254740991


toLocaleString :

number.toLocaleString(); // "1,234,567,890"

// A more complex example: 
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"


NumberFormat (ไม่รองรับ Safari ):

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

จากสิ่งที่ฉันตรวจสอบ (อย่างน้อย Firefox) พวกเขามีทั้งประสิทธิภาพที่เหมือนกันมากหรือน้อย


6
NumberFormat ไม่รองรับ Safari สำหรับทุกคนที่กำลังใช้งาน
marcovega

6
toLocaleString ไม่รองรับใน Safari ด้วย
Deepak Banka

3
การสนับสนุนเบราว์เซอร์จะมีการกล่าวถึงเสมอที่ด้านล่างของแต่ละหน้า MDN ซึ่งฉันได้เชื่อมโยง
vsync

5
toLocaleStringงานขั้นพื้นฐานเกี่ยวกับซาฟารี, ตัวเลือกไม่ได้
dandavis

3
การtoLocaleStringแก้ปัญหาอาจรวมถึงสถานที่ที่ต้องการด้วยเช่นtoLocaleString("en")กันเพราะรูปแบบภาษาอังกฤษใช้เครื่องหมายจุลภาค อย่างไรก็ตามหากtoLocaleString()ไม่มีตัวบ่งชี้สถานที่ทำงานในประเทศฝรั่งเศสก็จะให้ช่วงเวลาแทนเครื่องหมายจุลภาคเพราะนั่นคือสิ่งที่ใช้ในการแยกหลายพันคนในพื้นที่
Kamermans ของไมค์ 'Pomax'

112

ฉันขอแนะนำให้ใช้ number_format ของphpjs.org

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

อัพเดท 02/13/14

ผู้คนรายงานสิ่งนี้ไม่ได้ตามที่คาดไว้ดังนั้นฉันจึงทำJS Fiddleที่มีการทดสอบอัตโนมัติ

อัปเดต 26/11/2560

นี่คือซอที่ทำหน้าที่เป็นตัวอย่างข้อมูลย่อยที่มีการแก้ไขเล็กน้อย:

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

var exampleNumber = 1;
function test(expected, number, decimals, dec_point, thousands_sep)
{
    var actual = number_format(number, decimals, dec_point, thousands_sep);
    console.log(
        'Test case ' + exampleNumber + ': ' +
        '(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) +
        ', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' +
        ', thousands_sep: "' + (typeof thousands_sep === 'undefined' ? '(default)' : thousands_sep) + '")'
    );
    console.log('  => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", expected "' + expected + '".');
    exampleNumber++;
}

test('1,235',    1234.56);
test('1 234,56', 1234.56, 2, ',', ' ');
test('1234.57',  1234.5678, 2, '.', '');
test('67,00',    67, 2, ',', '.');
test('1,000',    1000);
test('67.31',    67.311, 2);
test('1,000.6',  1000.55, 1);
test('67.000,00000', 67000, 5, ',', '.');
test('1',        0.9, 0);
test('1.20',     '1.20', 2);
test('1.2000',   '1.20', 4);
test('1.200',    '1.2000', 3);
.as-console-wrapper {
  max-height: 100% !important;
}


ไม่ใช่ว่าฉันทำเครื่องหมายไว้ แต่ฉันเชื่อว่าผู้คนทำเช่นนั้นเพราะมันไม่ทำงาน ฉันพบว่าแม้แต่การทดสอบบางอย่างของคุณไม่ทำงาน
Andrew S

3
@Andrew S - มีเพียง 1 คนที่ได้ทำเครื่องหมายไว้ มันใช้งานได้ฉันใช้มันในรหัสของตัวเองหลายครั้ง มันไม่ใช่รหัสของฉัน (หรือการทดสอบของฉัน) ฉันอ้างอิงไซต์ที่มาจากซึ่งเป็นไซต์ที่รู้จักกันดี บางทีพวกเขาอาจมีรุ่นที่ปรับปรุงแล้ว) เนื่องจากรหัสที่คุณกำลังดูอยู่นั้นมีอายุ 3 ปี
Kerry Jones

13
@ernix - ผู้ดำเนินการขอ JavaScript คำตอบที่ฉันให้คือ JavaScript นี่คือการตีความ JavaScript ของฟังก์ชั่น PHP
Kerry Jones

2
@ernix - ทำงานได้อย่างตรงตามที่คาดไว้กับตัวอย่างที่ OP ให้ไว้ ฉันใส่ซอเพื่อที่คุณจะได้เห็น
Kerry Jones

4
@ernix - เอาล่ะ แต่ประเด็นก็คือว่ามันไม่ตรงกับสิ่งที่ OP ถาม มันมาจากเว็บไซต์อื่น (ไม่ได้ดูแลโดยฉันและฉันได้ระบุไว้ก่อนหน้านี้) และเมื่อให้ตัวแปรที่เหมาะสมมันทำงานตรงตามที่ระบุไว้ หากคุณเชื่อว่าเป็นข้อผิดพลาดโปรดติดต่อ phpjs.org หรือดูว่าพวกเขามีรุ่นที่อัปเดตหรือไม่
Kerry Jones

75

นี่เป็นรูปแบบของคำตอบของ @ mikez302 แต่ได้รับการแก้ไขเพื่อรองรับตัวเลขที่มีทศนิยม (ต่อความคิดเห็นของ @ neu-rah ที่ numberWithCommas (12345.6789) -> "12,345.6,789" แทน "12,345.6789"

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


67
function formatNumber (num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
}

print(formatNumber(2665));      // 2,665
print(formatNumber(102665));    // 102,665
print(formatNumber(111102665)); // 111,102,665

สิ่งนี้ทำอะไรได้บ้างที่คำตอบของฉันไม่ได้? Regex มีลักษณะแตกต่างกันเล็กน้อย แต่ดูเหมือนว่าควรทำในสิ่งเดียวกัน
อีเลียสซามาเรีย

8
มันสั้นกว่า :)
Tutankhamen

4
นี่คือสง่างาม สิ่งที่ฉันกำลังมองหา
แบบดั้งเดิม

4
จากblog.tompawlak.org/number-currency-formatting-javascriptหรือไม่ ปัญหาที่ทราบ: formatNumber (0.123456) = 0.123,456 การขาด lookbehind ใน JS ทำให้ยากต่อการแก้ไขด้วย regex ที่สง่างาม

1
123456789.123456789.toString (). แทนที่ (/ (\ d) (? = (\ d {3}) + \.) / g, '$ 1,') =>
123,456,789.12345679

53

ใช้การแสดงออกปกติ

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

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

ใช้ toLocaleString ()

var number = 123456.789;

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

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

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

อ้างอิงMDN: Number.prototype.toLocaleString ()

ใช้ Intl.NumberFormat ()

var number = 123456.789;

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

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

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

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

หมายเลขอ้างอิงระหว่างประเทศ

สาธิตที่นี่

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

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

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

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

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

</FORM>

ประสิทธิภาพ

ประสิทธิภาพ http://jsben.ch/sifRd


สิ่งนี้จะไม่ทำงานหากคุณกำลังพิมพ์แบบไดนามิก ถ้าคุณให้ค่ามันใช้งานได้ แต่ถ้าคุณป้อนค่าอย่างต่อเนื่องแบบไดนามิกจุลภาคจะถูกเพิ่มในตำแหน่งที่ไม่ถูกต้อง
Edgar Quintero

ฉันได้อัปเดตตัวอย่างด้านล่างคำตอบแล้ว เมื่อป้อนค่าแบบไดนามิกในกล่องข้อความ คุณทดสอบลอง @EdgarQuintero
Quang

39

Intl.NumberFormat

ฟังก์ชั่น Native JS สนับสนุนโดย IE11, Edge, Safari ล่าสุด, Chrome, Firefox, Opera, Safari บน iOS และ Chrome บน Android

var number = 3500;

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

คำตอบของฉันได้รับการอัปเดตตามความคิดเห็นของคุณ ขอบคุณ!
ดัสตินซัน

35

ขอบคุณทุกคนสำหรับคำตอบของพวกเขา ฉันได้สร้างคำตอบบางคำเพื่อสร้างโซลูชัน "หนึ่งขนาดเหมาะกับทุกคน" มากขึ้น

ข้อมูลแรกเพิ่มฟังก์ชั่นที่เลียนแบบPHP 's number_format()เพื่อต้นแบบจำนวน ถ้าฉันกำลังจัดรูปแบบตัวเลขฉันมักจะต้องการตำแหน่งทศนิยมดังนั้นฟังก์ชั่นใช้ในจำนวนตำแหน่งทศนิยมที่จะแสดง บางประเทศใช้จุลภาคเป็นทศนิยมและทศนิยมเป็นตัวคั่นหลักพันดังนั้นฟังก์ชันอนุญาตให้ตั้งค่าตัวคั่นเหล่านี้

Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.toFixed(decimals).split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);

    return parts.join(dec_point);
}

คุณจะใช้สิ่งนี้ดังนี้:

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

ฉันพบว่าฉันมักจะต้องได้รับหมายเลขกลับมาสำหรับการดำเนินการทางคณิตศาสตร์ แต่ parseFloat แปลง 5,000 ถึง 5 เพียงแค่รับลำดับของค่าจำนวนเต็มแรก ดังนั้นฉันจึงสร้างฟังก์ชั่นการแปลงลอยตัวของตัวเองและเพิ่มลงในเครื่องต้นแบบ String

String.prototype.getFloat = function(dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.split(dec_point);
    var re = new RegExp("[" + thousands_sep + "]");
    parts[0] = parts[0].replace(re, '');

    return parseFloat(parts.join(dec_point));
}

ตอนนี้คุณสามารถใช้ทั้งสองฟังก์ชั่นได้ดังต่อไปนี้:

var foo = 5000;
var fooString = foo.numberFormat(2); // The string 5,000.00
var fooFloat = fooString.getFloat(); // The number 5000;

console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00

2
ดีมากฉันยืมวิธีแรก;) แต่มันไม่ได้ผลลัพธ์ที่ถูกต้องเมื่อคุณต้องการใช้รูปแบบยุโรปและจำนวนเป็นเศษส่วน บรรทัดที่ 5 ควรเป็น:var parts = this.toFixed(decimals).toString().split('.');
vbwx

คุณพูดถูก! toFixed () เปลี่ยนเครื่องหมายจุลภาคเป็นจุดและดังนั้น '.' var dec_pointควรจะนำมาใช้แทน ขอบคุณสำหรับการชี้ให้เห็นว่า
ไม่มี

คุณสามารถสร้างโมดูล npm สำหรับสิ่งนี้ได้ไหม
chovy

3
@ J.Money. toString ไม่จำเป็น toFixed จะส่งคืนสตริงแล้ว
Ariel

ผมไม่ทราบว่าทำไมคุณได้กล่าว PHP ที่นี่ที่ทั้งหมดหรือรับฟังก์ชั่น prototipical ที่แล้วที่มีอยู่
vSync

27

ฉันค่อนข้างประทับใจกับจำนวนคำตอบที่คำถามนี้ได้รับ ฉันชอบคำตอบโดยuKolka :

n.toLocaleString()

แต่น่าเสียดายที่ในบางพื้นที่เช่นสเปนมันใช้งานไม่ได้ (IMHO) ตามที่คาดไว้สำหรับตัวเลขต่ำกว่า 10,000:

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

จะช่วยให้ไม่10001.000

ดูtoLocaleString ไม่ทำงานกับตัวเลขที่น้อยกว่า 10,000 ในเบราว์เซอร์ทั้งหมดเพื่อทราบสาเหตุ

ดังนั้นฉันต้องใช้คำตอบโดยElias Zamariaการเลือกตัวคั่นที่ถูกต้องพัน:

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

อันนี้ใช้งานได้ดีเป็นหนึ่งซับสำหรับสถานที่ทั้งสองที่ใช้,หรือ.เป็นตัวคั่นหลักพันและเริ่มทำงานจาก 1,000 ในทุกกรณี

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

ให้1.000กับบริบทโลแคลสเปน

หากคุณต้องการควบคุมการจัดรูปแบบตัวเลขอย่างสมบูรณ์คุณอาจลองทำสิ่งต่อไปนี้:

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

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

console.log(final)

1,234.57จะช่วยให้

อันนี้ไม่จำเป็นต้องมีการแสดงออกปกติ มันทำงานได้โดยการปรับจำนวนให้เป็นจำนวนทศนิยมที่ต้องการtoFixedก่อนแล้วหารมันรอบจุดทศนิยม.ถ้ามี ทางด้านซ้ายจะกลายเป็นอาเรย์ของตัวเลขที่กลับด้าน จากนั้นจะมีการเพิ่มตัวคั่นหลักพันทุกสามหลักจากจุดเริ่มต้นและผลลัพธ์กลับด้านอีกครั้ง ผลสุดท้ายคือการรวมกันของทั้งสองส่วน เครื่องหมายของหมายเลขอินพุตจะถูกลบออกMath.absก่อนแล้วค่อยใส่กลับหากจำเป็น

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


23

ฉันคิดว่านี่เป็นนิพจน์ปกติที่สั้นที่สุดที่ทำ:

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

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

ฉันตรวจสอบมันด้วยตัวเลขสองสามตัวและใช้งานได้


ใช้งานได้ดีถ้าคุณไม่มีหมายเลขลอยตัวที่มีมากกว่า 3 หมายเลขหลังจากตัวคั่นในกรณีนี้เป็นจุด มิฉะนั้นจะเพิ่มเครื่องหมายจุลภาคด้วย "1234567890.1234567890" .replace (/ \ B (? = (\ d {3}) + \ b) / g, ",") สิ่งนี้ใช้ไม่ได้ผล ส่งคืน "1,234,567,890.1,234,567,890"
Marcio

1
ใช้งานได้ดีสำหรับสกุลเงิน! เพียงปัดเศษตัวเลขของคุณก่อนที่จะเพิ่มเครื่องหมายจุลภาค
Kyle Chadha

1
มันเพิ่มหลังจุดทศนิยม: 12.3456 ".replace (/ \ B (? = (\ d {3}) + \ b) / g,", ")" == 12.3,456
Shree Tiwari

21

Number.prototype.toLocaleString()จะได้รับน่ากลัวถ้ามันถูกจัดให้กำเนิดโดยเบราว์เซอร์(Safari)

ฉันตรวจสอบคำตอบอื่น ๆ ทั้งหมดแล้ว แต่ดูเหมือนว่าจะไม่มีใครเติมได้เลย นี่คือ poc ต่อซึ่งจริงๆแล้วเป็นการรวมกันของสองคำตอบแรก; ถ้าtoLocaleStringใช้มันใช้มันถ้ามันไม่ได้ใช้ฟังก์ชั่นที่กำหนดเอง

var putThousandsSeparators;

putThousandsSeparators = function(value, sep) {
  if (sep == null) {
    sep = ',';
  }
  // check if it needs formatting
  if (value.toString() === value.toLocaleString()) {
    // split decimals
    var parts = value.toString().split('.')
    // format whole numbers
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
    // put them back together
    value = parts[1] ? parts.join('.') : parts[0];
  } else {
    value = value.toLocaleString();
  }
  return value;
};

alert(putThousandsSeparators(1234567.890));


1
ระวังว่า polyfill จะใช้ได้กับตัวเลขที่มีทศนิยมไม่เกิน 3 ตัวเท่านั้น สำหรับเช่น: ออกจะ0.12345 0.12,345การใช้งานที่ดีสำหรับสิ่งนี้สามารถพบได้ในunderscore.string
Andy

คุณถูกต้องการใส่value > 1000เงื่อนไขหากแก้ไขในกรณีนั้นอย่างไรก็ตามนี่เป็น poc และแน่นอนว่ารุ่นทดสอบที่ดีกว่าสามารถพบได้ที่อื่นขอขอบคุณสำหรับการชี้ให้เห็น
Sinan

1
มันไม่เพียงพอที่จะใส่value > 1000เพราะมันจะเหมือนกันสำหรับจำนวนใด ๆ และมากกว่า 3 ทศนิยม เช่นผลตอบแทน1000.12345 1,000.12,345คำตอบของคุณยอดเยี่ยมและถูกต้อง แต่ก็ไม่สมบูรณ์ ฉันแค่พยายามชี้ให้คนอื่น ๆ ที่อาจสะดุดกับคำตอบของคุณและเพียงแค่คัดลอก / พาสต้าโดยไม่ต้องทดสอบกับข้อมูลอินพุตอื่น
Andy

1
เอาล่ะนี่ต้องการการแก้ไขอื่น :) ฉันเห็นด้วย แต่อย่างน้อยตอนนี้ก็น่าจะใช้ได้สำหรับกรณีส่วนใหญ่
Sinan

18

ตัวคั่นหลักพันสามารถแทรกในลักษณะที่เป็นมิตรกับสากลโดยใช้Intlวัตถุของเบราว์เซอร์:

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

ดูบทความของ MDN เกี่ยวกับ NumberFormatเพิ่มเติมคุณสามารถระบุลักษณะการทำงานของโลแคลหรือค่าเริ่มต้นให้กับผู้ใช้ นี่เป็นสิ่งที่เข้าใจผิดได้มากกว่าเพราะเคารพความแตกต่าง หลายประเทศใช้จุดเพื่อแยกตัวเลขในขณะที่เครื่องหมายจุลภาคหมายถึงทศนิยม

Intl.NumberFormat ยังไม่พร้อมใช้งานในเบราว์เซอร์ทั้งหมด แต่สามารถใช้งานได้กับ Chrome, Opera และ IE ล่าสุด Firefox รุ่นถัดไปควรสนับสนุน ดูเหมือนว่า Webkit จะไม่มีกำหนดเวลาสำหรับการนำไปใช้งาน


2
แม้ว่านี่จะยอดเยี่ยมหากเราสามารถใช้ฟังก์ชั่นในตัวที่เรียบง่าย แต่ก็มีการใช้งานเบราว์เซอร์ที่แย่มาก ตัวอย่างเช่น IE 8-10 และ Safari ทั้งหมดไม่สนับสนุนสิ่งนี้
Blaine Kasten

@BlaineKasten มีโพลีฟิลที่เข้ากันได้อย่างสมบูรณ์สำหรับเบราว์เซอร์รุ่นเก่าที่มีให้ที่นี่: github.com/andyearnshaw/Intl.jsมันใหญ่ แต่ก็ใช้งานได้
Mahn

1
พร้อมใช้งานผ่าน pollyfill CDN (คืนสิ่งที่จำเป็นตามผู้ใช้): cdn.polyfill.io/v2/polyfill.min.js?features=Intl
Kevin

มีปัญหาในการจัดรูปแบบจำนวนมากด้วย toLocaleString สิ่งนี้ใช้งานได้ดี (กับโพลีฟิล)
ถาม _ คำตอบ

18

คุณสามารถใช้ขั้นตอนนี้เพื่อจัดรูปแบบสกุลเงินที่คุณต้องการ

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

สำหรับข้อมูลเพิ่มเติมคุณสามารถเข้าถึงลิงค์นี้

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


นี่เป็นคำตอบที่ถูกต้องพกพาและถูกต้อง หวังว่าฉันจะสามารถโหวตมากกว่าหนึ่งครั้ง
Jared Smith

14

หากคุณกำลังจัดการกับค่าสกุลเงินและการจัดรูปแบบเป็นจำนวนมากมันอาจคุ้มค่าที่จะเพิ่มการบัญชีขนาดจิ๋วที่จัดการกับกรณีและขอบที่ จำกัด จำนวนมาก:

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

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

// Negative values are formatted nicely, too:
accounting.formatMoney(-500000, "£ ", 0); // £ -500,000

// Simple `format` string allows control of symbol position [%v = value, %s = symbol]:
accounting.formatMoney(5318008, { symbol: "GBP",  format: "%v %s" }); // 5,318,008.00 GBP

1
ลิงก์ใช้งานไม่ได้อีกต่อไป แต่หน้าตาคล้ายกับอันนี้: openexchangerates.github.io/accounting.js
ush189

13

รหัสต่อไปนี้ใช้การสแกนด้วยถ่านดังนั้นจึงไม่มี regex

function commafy( num){
  var parts = (''+(num<0?-num:num)).split("."), s=parts[0], L, i=L= s.length, o='';
  while(i--){ o = (i===0?'':((L-i)%3?'':',')) 
                  +s.charAt(i) +o }
  return (num<0?'-':'') + o + (parts[1] ? '.' + parts[1] : ''); 
}

มันแสดงให้เห็นถึงประสิทธิภาพที่มีแนวโน้ม: http://jsperf.com/number-formatting-with-commas/5

2015.4.26: การแก้ไขเล็กน้อยเพื่อแก้ไขปัญหาเมื่อ num <0 ดูhttps://jsfiddle.net/runsun/p5tqqvs3/


สิ่งนี้ไม่สามารถใช้ได้กับcommafy(-123456)มัน-,123,456
wrossmck

มันเยี่ยมมาก! ขอบคุณที่รวบรวม jsperf
fregante

ตัวอย่างนี้เป็นสัตว์ประหลาดแน่นอนการกระทำทุกอย่าง
NiCk Newman

13

นี่คือฟังก์ชั่นง่าย ๆ ที่แทรกเครื่องหมายจุลภาคสำหรับตัวคั่นหลักพัน มันใช้ฟังก์ชั่นอาร์เรย์มากกว่า RegEx

/**
 * Format a number as a string with commas separating the thousands.
 * @param num - The number to be formatted (e.g. 10000)
 * @return A string representing the formatted number (e.g. "10,000")
 */
var formatNumber = function(num) {
    var array = num.toString().split('');
    var index = -3;
    while (array.length + index > 0) {
        array.splice(index, 0, ',');
        // Decrement by 4 since we just added another unit to the array.
        index -= 4;
    }
    return array.join('');
};

ลิงค์ CodeSandbox พร้อมตัวอย่าง: https://codesandbox.io/s/p38k63w0vq


1
สวัสดี .. ตัวอย่างนี้ดีมาก แต่มันจะใส่เครื่องหมายจุลภาคสำหรับส่วนทศนิยมด้วย เพียงแค่การแก้ไข: ฟังก์ชั่น formatNumber (จำนวน) {var decimalPart = ''; num = num.toString (); if (num.indexOf ('.')! = -1) {decimalPart = '.' + num.split ('.') [1]; num = parseInt (num.split ('.') [0]); } var array = num.toString (). split (''); ดัชนี var = -3; ในขณะที่ (array.length + index> 0) {array.splice (index, 0, ','); // ลดลง 4 เนื่องจากเราเพิ่งเพิ่มหน่วยอื่นลงในอาร์เรย์ ดัชนี - = 4; } return array.join ('') + decimalPart; };
Aki143S

ขอบคุณครับ นี่คือสิ่งที่ฉันต้องการ
Amir Hossein Ahmadi

11

ใช้รหัสนี้เพื่อจัดการรูปแบบสกุลเงินสำหรับอินเดีย รหัสประเทศสามารถเปลี่ยนแปลงได้เพื่อจัดการกับสกุลเงินประเทศอื่น ๆ

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

// Use it.

formatter.format(amount);

เอาท์พุท:

3,50,256.95

ในขณะที่รหัสนี้อาจตอบคำถามให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือทำไมมันแก้ปัญหาจะปรับปรุงค่าระยะยาวของคำตอบ อ่าน
Shanteshwar Inde

@ShanteshwarInde ฉันจะเพิ่มบริบทเพิ่มเติมเพื่อปรับปรุงคำตอบที่แน่นอน
Bathri Nathan

11

คุณยังสามารถใช้ตัวสร้างIntl.NumberFormat นี่คือวิธีที่คุณสามารถทำได้

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

โหนดนี้ไม่ทำงาน js มันไม่ได้ให้การตอบสนองในรูปแบบของอินเดีย
Suraj Dalvi

7

ฉันเขียนสิ่งนี้ก่อนที่จะสะดุดกับโพสต์นี้ ไม่มี regex และคุณสามารถเข้าใจรหัสได้จริง

$(function(){
  
  function insertCommas(s) {

    // get stuff before the dot
    var d = s.indexOf('.');
    var s2 = d === -1 ? s : s.slice(0, d);

    // insert commas every 3 digits from the right
    for (var i = s2.length - 3; i > 0; i -= 3)
      s2 = s2.slice(0, i) + ',' + s2.slice(i);

    // append fractional part
    if (d !== -1)
      s2 += s.slice(d);

    return s2;

  }
  
  
  $('#theDudeAbides').text( insertCommas('1234567.89012' ) );
  
  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="theDudeAbides"></div>


1
ฉันเพิ่ม s.toString () ที่จุดเริ่มต้นของฟังก์ชันเพื่อให้สามารถรับตัวเลขได้เช่นกันไม่ใช่เฉพาะสตริง นี่คือคำตอบที่ฉันต้องการเพราะสามารถอ่านได้กระชับและไม่มีข้อบกพร่องที่ดูเหมือนว่าคำตอบของ regex
FeFiFoFu

7
var formatNumber = function (number) {
  var splitNum;
  number = Math.abs(number);
  number = number.toFixed(2);
  splitNum = number.split('.');
  splitNum[0] = splitNum[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return splitNum.join(".");
}

แก้ไข: ฟังก์ชั่นจะทำงานเฉพาะกับจำนวนบวก สำหรับ exmaple:

var number = -123123231232;
formatNumber(number)

เอาท์พุท: "123,123,231,232"

แต่เพื่อตอบคำถามข้างต้นtoLocaleString()วิธีการเพียงแค่แก้ปัญหา

var number = 123123231232;
    number.toLocaleString()

เอาท์พุท: "123,123,231,232"

เชียร์!


1
ในขณะที่รหัสนี้อาจตอบคำถามให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือทำไมมันแก้ปัญหาจะปรับปรุงค่าระยะยาวของคำตอบ
โดนัลด์ดั๊ก

1
สคริปต์ที่ดี แต่ใช้ไม่ได้กับจำนวนลบ
Ralph David Abernathy

7

คำตอบของฉันคือคำตอบเดียวที่แทนที่ jQuery ด้วยทางเลือกที่เหมาะสมกว่า:

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

โซลูชันนี้ไม่เพียง แต่เพิ่มเครื่องหมายจุลภาค แต่ยังปัดเศษเป็นเงินที่ใกล้ที่สุดในกรณีที่คุณป้อนจำนวนเงินเช่น$(1000.9999)คุณจะได้รับ $ 1,001.00 นอกจากนี้ค่าที่คุณป้อนสามารถเป็นตัวเลขหรือสตริงได้อย่างปลอดภัย มันไม่สำคัญ

หากคุณกำลังจัดการกับเงิน แต่ไม่ต้องการให้เครื่องหมายดอลลาร์ชั้นนำแสดงตามจำนวนเงินคุณยังสามารถเพิ่มฟังก์ชันนี้ซึ่งใช้ฟังก์ชันก่อนหน้านี้ แต่ลบฟังก์ชัน$:

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

หากคุณไม่ได้จัดการกับเงินและมีความต้องการการจัดรูปแบบทศนิยมที่แตกต่างกันนี่คือฟังก์ชันที่หลากหลายมากขึ้น:

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

โอ้และความจริงที่ว่ารหัสนี้ไม่สามารถใช้งานได้ใน Internet Explorer รุ่นเก่าโดยเจตนา ฉันพยายามทำลาย IE ทุกครั้งที่ฉันสามารถจับได้ว่าไม่รองรับมาตรฐานที่ทันสมัย

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


1
Number (n) .toLocaleString () ดูเหมือนคำตอบที่ดีที่สุด แต่คุณอาจต้องการใช้บางอย่างเช่น Intl.NumberFormat ('en-US') รูปแบบใหม่ (n) แทนที่จะลอกเครื่องหมายดอลลาร์และทศนิยมถ้าทั้งหมด ผู้ใช้ต้องการจุลภาคในจำนวนของพวกเขา
bmacnaughton

@bmacnaughton: นั่นเป็นจุดที่ดีเมื่อคุณไม่ได้จัดการเรื่องเงิน อย่างไรก็ตามหากคุณกำลังรับมือกับเงินและเพียงแค่ "ไม่ต้องการเครื่องหมายดอลลาร์ชั้นนำ" Number (1,000.50) .toLocaleString () จะสร้าง '1,000.5' ซึ่งจะลบศูนย์ที่ไม่มีนัยสำคัญที่มักจะเก็บไว้เมื่อแสดงค่าเงิน แม้ว่าจะมีความคิดเห็นที่ดีทุกคนควรรู้สิ่งที่คุณพูด
Lonnie Best

6

สำหรับฉันคำตอบที่ดีที่สุดคือใช้ toLocaleString เหมือนที่สมาชิกบางคนพูด หากคุณต้องการรวมสัญลักษณ์ '$' เพียงเพิ่ม languaje และตัวเลือกประเภท นี่คือตัวอย่างในการจัดรูปแบบตัวเลขเป็นเปโซเม็กซิโก

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

ทางลัด

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

5

ให้ฉันพยายามปรับปรุงคำตอบของuKolkaและอาจช่วยให้ผู้อื่นประหยัดเวลา

ใช้Numeral.js

document.body.textContent = numeral(1234567).format('0,0');
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>

คุณควรไปกับNumber.prototype.toLocaleString ()เฉพาะเมื่อความเข้ากันได้ของเบราว์เซอร์ไม่ใช่ปัญหา


สิ่งนี้เป็นแรงบันดาลใจให้ฉันติดตั้งตัวเลข
npm

5

อีกทางเลือกหนึ่งรองรับทศนิยมตัวคั่นและเนกาทีฟต่าง ๆ

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

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

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

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

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

    return f;
}

การแก้ไขบางอย่างโดย @Jignesh Sanghani อย่าลืมโหวตความคิดเห็นของเขา


สมบูรณ์แบบสำหรับฉันเพิ่งเพิ่มบรรทัดใหม่เพื่อลบการจัดรูปแบบก่อนการประมวลผล
Dennis Heiden

2
fn.substr(0, i)เปลี่ยนn.substr(0, i)และแทนที่ด้วยnumber.toFixed(dp).split('.')[1] parseFloat(number).toFixed(dp).split('.')[1]เพราะเมื่อฉันใช้โดยตรงมันทำให้ฉันมีข้อผิดพลาด โปรดอัปเดตรหัสของคุณ
Jignesh Sanghani

มีข้อบกพร่อง. จำนวนเพิ่มขึ้น การเรียก exampel นั้นยอดเยี่ยมมาก!
mmm

การเปลี่ยนเพดานไปที่พื้นคงที่ แต่ไม่แน่ใจว่าจะมีปัญหาอื่นเกิดขึ้นอีก
mmm

1
ลอง Math.floor (-75.1);)
mmm

4

ฉันคิดว่าฟังก์ชั่นนี้จะดูแลทุกปัญหาที่เกี่ยวข้องกับปัญหานี้

function commaFormat(inputString) {
    inputString = inputString.toString();
    var decimalPart = "";
    if (inputString.indexOf('.') != -1) {
        //alert("decimal number");
        inputString = inputString.split(".");
        decimalPart = "." + inputString[1];
        inputString = inputString[0];
        //alert(inputString);
        //alert(decimalPart);

    }
    var outputString = "";
    var count = 0;
    for (var i = inputString.length - 1; i >= 0 && inputString.charAt(i) != '-'; i--) {
        //alert("inside for" + inputString.charAt(i) + "and count=" + count + " and outputString=" + outputString);
        if (count == 3) {
            outputString += ",";
            count = 0;
        }
        outputString += inputString.charAt(i);
        count++;
    }
    if (inputString.charAt(0) == '-') {
        outputString += "-";
    }
    //alert(outputString);
    //alert(outputString.split("").reverse().join(""));
    return outputString.split("").reverse().join("") + decimalPart;
}

4

สำหรับผู้ใช้ Google ในอนาคต (หรืออาจไม่จำเป็นต้องเป็น 'ชาว Google'):

โซลูชันทั้งหมดที่กล่าวมาข้างต้นนั้นยอดเยี่ยมอย่างไรก็ตาม RegExp อาจเป็นสิ่งที่ไม่ดีอย่างยิ่งที่จะใช้ในสถานการณ์เช่นนั้น

ดังนั้นใช่คุณอาจใช้ตัวเลือกบางอย่างที่เสนอหรือแม้กระทั่งเขียนสิ่งดั้งเดิม แต่มีประโยชน์เช่น:

const strToNum = str => {

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

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

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

};

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

regexp ที่ใช้ที่นี่ค่อนข้างง่ายและวนรอบจะแม่นยำตามจำนวนครั้งที่ใช้ในการทำงานให้เสร็จ

และคุณอาจปรับให้ดีขึ้นกว่านี้คือรหัส "DRYify" และอื่น ๆ

กระนั้น

(-1234567.0987).toLocaleString();

(ในสถานการณ์ส่วนใหญ่) จะเป็นทางเลือกที่ดีกว่า

จุดไม่ได้อยู่ในความเร็วของการดำเนินการหรือในความเข้ากันได้ข้ามเบราว์เซอร์

ในสถานการณ์ที่คุณต้องการแสดงจำนวนผลลัพธ์ให้กับผู้ใช้วิธี. toLocaleString () ช่วยให้คุณมีพลังวิเศษในการพูดภาษาเดียวกันกับผู้ใช้เว็บไซต์หรือแอปของคุณ

วิธีการตามเอกสาร ECMAScript นี้เปิดตัวในปี 1999 และฉันเชื่อว่าเหตุผลที่เป็นความหวังว่าอินเทอร์เน็ตในบางจุดจะเชื่อมโยงผู้คนทั่วโลกดังนั้นต้องการเครื่องมือ "การปรับใช้ภายใน" บางอย่าง

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

เห็นได้ชัดว่าการพิจารณาความหลากหลายของผู้คนเป็นไปไม่ได้ที่จะรับประกัน UX ที่สมบูรณ์แบบสำหรับทุกคนเพราะเราพูดภาษาต่าง ๆ ให้ความสำคัญกับสิ่งต่าง ๆ ฯลฯ และด้วยเหตุนี้สิ่งสำคัญคือการพยายาม จำกัด วงให้มากที่สุด .

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

สำหรับฉันแล้วการใช้ RegExp แทน. toLocaleString () ในสถานการณ์เช่นนั้นฟังดูนิดหน่อยเหมือนการสร้างแอพนาฬิกาด้วย JavaScript และเขียนโค้ดแบบยากดังนั้นมันจะแสดงเวลาปรากเท่านั้น (ซึ่งค่อนข้างไร้ประโยชน์สำหรับ คนที่ไม่ได้อยู่ในปราก) แม้ว่าพฤติกรรมเริ่มต้นของ

new Date();

คือการส่งคืนข้อมูลตามนาฬิกาของผู้ใช้ขั้นสุดท้าย


ทำไมคุณถึงเขียนฟังก์ชันด้วย const และ =>
OG Sean

@OGSean ฉันทำเช่นนี้เสมอเพราะเป็นวิธีที่สะดวกที่สุดในการประกาศตัวแปรและฟังก์ชั่น นอกจากนี้ฉันคิดว่ามันจะช่วยให้รหัสสะอาดและสั้นลง
Igor Bykov

4

ของฉันความจริงการแก้ปัญหาการแสดงออกปกติเท่านั้นสำหรับผู้ที่รักหนึ่งสมุทร

คุณเห็นผู้เล่นที่กระตือรือร้นด้านบนหรือไม่ บางทีคุณสามารถตีกอล์ฟออกไปได้ นี่คือจังหวะของฉัน

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

ใช้THIN SPACE (U + 2009) สำหรับตัวคั่นหลักพันเป็นระบบสากลของหน่วยงานที่กล่าวถึงในฉบับที่แปด(2549)ของการตีพิมพ์ของพวกเขา“ SI Brochure: The International System of Units (SI) (ดู§5.3 0.4.) ฉบับที่เก้า(2019)แนะนำให้ใช้พื้นที่สำหรับมัน (ดู§5.4.4) คุณสามารถใช้สิ่งที่คุณต้องการรวมถึงเครื่องหมายจุลภาค


ดู.

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

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


มันทำงานยังไง?

สำหรับส่วนจำนวนเต็ม

.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ")
  • .replace(……, " I ") ใส่“ ฉัน”
    • /……/g ที่แต่ละ
      • \B ในระหว่างตัวเลขสองหลักที่อยู่ติดกัน
        • (?=……)LOOKAHEAD เชิงบวกซึ่งเป็นส่วนที่ถูกต้อง
          • (\d{3})+ ชิ้นหนึ่งสามหลักขึ้นไป
          • \b ตามด้วยตัวเลขที่ไม่ใช่ตัวเลขเช่นจุดสิ้นสุดจุดสิ้นสุดของสตริงและอื่น ๆ
        • (?<!……)การค้นหาลบทางลบยกเว้นคนที่มีส่วนด้านซ้าย
          • \.\d+ เป็นจุดตามด้วยตัวเลข (“ มีตัวคั่นทศนิยม”)

สำหรับส่วนทศนิยม

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ") ใส่“ F”
    • /……/g ที่แต่ละ
      • \B ในระหว่างตัวเลขสองหลักที่อยู่ติดกัน
        • (?<=……)LOOKBEHIND เป็นบวกซึ่งเป็นส่วนที่เหลือ
          • \. ตัวแยกทศนิยม
          • (\d{3})+ ตามด้วยชิ้นหลักสามหลักขึ้นไป

คลาสอักขระและขอบเขต

\d

ตรงกับตัวเลขใด ๆ (ตัวเลขอาหรับ) [0-9]เทียบเท่า

ตัวอย่างเช่น,

  • /\d/หรือ/[0-9]/การแข่งขันใน2B2 is the suite number

\b

จับคู่ขอบเขตของคำขอบเขตของคำนี่คือตำแหน่งที่อักขระคำไม่ได้ถูกติดตามหรือนำหน้าด้วยอักขระคำอื่นเช่นระหว่างตัวอักษรและช่องว่าง โปรดทราบว่าขอบเขตคำที่ตรงกันไม่รวมอยู่ในการแข่งขัน กล่าวอีกนัยหนึ่งความยาวของขอบเขตคำที่ตรงกันคือศูนย์

ตัวอย่าง:

  • /\bm/ตรงกับmในmoon;
  • /oo\b/ไม่ตรงกับooในmoonเพราะooตามมาด้วยnซึ่งเป็นตัวอักษรคำ;
  • /oon\b/ตรงกับoonในmoonเพราะoonเป็นจุดสิ้นสุดของสตริงจึงไม่ตามด้วยตัวอักษรคำ;
  • /\w\b\w/ จะไม่ตรงกับสิ่งใดเลยเพราะตัวอักษรของคำนั้นไม่สามารถตามด้วยอักขระที่ไม่ใช่คำและตัวอักษร

\B

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

ตัวอย่างเช่น,

  • /\Bon/การแข่งขันonในat noon;
  • /ye\B/การแข่งขันในyepossibly yesterday

ความเข้ากันได้ของเบราว์เซอร์


3

ฉันเพิ่ม tofixed เข้ากับโซลูชันของAki143S วิธีนี้ใช้จุดสำหรับตัวคั่นหลักพันและเครื่องหมายจุลภาคเพื่อความแม่นยำ

function formatNumber( num, fixed ) { 
    var decimalPart;

    var array = Math.floor(num).toString().split('');
    var index = -3; 
    while ( array.length + index > 0 ) { 
        array.splice( index, 0, '.' );              
        index -= 4;
    }

    if(fixed > 0){
        decimalPart = num.toFixed(fixed).split(".")[1];
        return array.join('') + "," + decimalPart; 
    }
    return array.join(''); 
};

ตัวอย่าง;

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

3

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

function format(num, fix) {
    var p = num.toFixed(fix).split(".");
    return p[0].split("").reduceRight(function(acc, num, i, orig) {
        if ("-" === num && 0 === i) {
            return num + acc;
        }
        var pos = orig.length - i - 1
        return  num + (pos && !(pos % 3) ? "," : "") + acc;
    }, "") + (p[1] ? "." + p[1] : "");
}

ตัวอย่างบางส่วน:

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

สิ่งนี้ไม่สามารถใช้ได้กับformat(-123456)มัน-,123,456
wrossmck

1
คงที่ (แม้ว่าอาจมีวิธีที่หรูหรากว่าในการทำโดยไม่ตรวจสอบเครื่องหมายทุกครั้ง) ไม่ว่าในกรณีใดการอัปเดตทำให้สามารถใช้ตัวเลขที่ติดลบ
Wayne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.