Как напечатать число с запятыми как разделители тысяч в JavaScript

Я пытаюсь напечатать целое число в 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;
}

Есть ли более простой или элегантный способ сделать это? Было бы неплохо, если бы он работал с поплавками, но это не обязательно. Для принятия решения между периодами и запятыми не обязательно быть языковым.

Ответы

Ответ 1

Я использовал идею из ответа Керри, но упростил ее, так как я просто искал что-то простое для моей конкретной цели. Вот что я сделал:

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

Это все, что вам действительно нужно знать.

@Neils Bom спросил, как работает регулярное выражение. Мое объяснение довольно длинное. Это не помещается в комментариях, и я не знаю, где еще поместить это, поэтому я делаю это здесь. Если у кого-то есть какие-либо предложения относительно того, где его поставить, пожалуйста, дайте мне знать.

В регулярном выражении используются 2 утверждения предпросмотра: положительное для поиска любой точки в строке, которая содержит несколько цифр в строке после нее, и отрицательное утверждение, чтобы убедиться, что эта точка содержит только 3 цифры. Выражение замены ставит запятую там.

Например, если вы передадите ему "123456789.01", положительное утверждение будет совпадать с каждой точкой слева от 7 (поскольку "789" кратно 3 цифрам, "678" кратно 3 цифрам, "567", так далее.). Отрицательное утверждение проверяет, что кратное 3 цифрам не имеет никаких цифр после него. У "789" есть точка после него, поэтому она точно кратна 3 цифрам, поэтому запятая идет туда. "678" является кратным 3 цифрам, но после него стоит "9", поэтому эти 3 цифры являются частью группы из 4, и запятая здесь не идет. Аналогично для "567". "456789" - это 6 цифр, что кратно 3, поэтому перед этим стоит запятая. "345678" - это кратное 3, но после него стоит "9", поэтому запятая не идет. И так далее. "\ B" не позволяет регулярному выражению ставить запятую в начале строки.

@neu-rah упомянул, что эта функция добавляет запятые в нежелательные места, если после десятичной точки больше 3 цифр. Если это проблема, вы можете использовать эту функцию:

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

Ответ 2

Я удивлен, что никто не упомянул Number.prototype.toLocaleString. Он реализован в JavaScript 1.5 (который был представлен в 1999 году), поэтому он в основном поддерживается во всех основных браузерах.

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

Это также работает в Node.js с v0.12 через включение Intl

Просто обратите внимание, что эта функция возвращает строку, а не число.

Если вы хотите что-то другое, Numeral.js может быть интересным.

Ответ 3

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

⚠ Помните, что javascript имеет максимальное целое число 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), они более или менее похожи на производительность.

Ответ 4

Я предлагаю использовать phpjs.org number_format()

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

Вот эта скрипка как фрагмент стека со слегка измененным выводом:

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

Ответ 5

Это вариация ответа @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] : "");
}

Ответ 6

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

Ответ 7

Использование регулярного выражения

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

ref 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"

ref Intl.NumberFormat

ДЕМО НА ЗДЕСЬ

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

Ответ 8

Intl.NumberFormat

Нативная функция 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

Ответ 9

Спасибо всем за их ответы. Я отработал некоторые ответы, чтобы сделать более "одноразовое решение".

Первый фрагмент добавляет функцию, которая подражает PHP number_format() прототипу Number. Если я форматирую число, я обычно хочу десятичные места, поэтому функция отображает число десятичных знаков. Некоторые страны используют запятые как десятичные и десятичные числа в качестве разделителя тысяч, поэтому функция позволяет устанавливать эти разделители.

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, просто беря первую последовательность целых значений. Поэтому я создал свою собственную функцию преобразования float и добавил ее в прототип 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

Ответ 10

Я думаю, что это кратчайшее регулярное выражение, которое делает это:

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

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

Я проверил его на несколько цифр, и он сработал.

Ответ 11

Number.prototype.toLocaleString() было бы потрясающе, если бы оно было предоставлено изначально всеми браузерами (Safari).

Я проверил все остальные ответы, но никто не казался polyfill. Вот пример этого, который на самом деле представляет собой комбинацию первых двух ответов; если 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));

Ответ 12

Разделитель тысяч может быть вставлен в международном режиме с использованием объекта Intl браузера:

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

Подробнее см. статью MDN о NumberFormat, вы можете указать поведение локали или по умолчанию для пользователя. Это немного более надежный, поскольку он уважает локальные различия; многие страны используют периоды для разделения цифр, а запятая обозначает десятичные знаки.

Intl.NumberFormat пока недоступен во всех браузерах, но он работает в последних версиях Chrome, Opera и IE. Следующая версия Firefox должна поддерживать его. Webkit, похоже, не имеет временной шкалы для реализации.

Ответ 13

Вы можете использовать эту процедуру для форматирования необходимой валюты.

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/

Ответ 14

если вы имеете дело с валютными ценностями и форматированием, то может быть стоит добавить маленький accounting.js, который обрабатывает множество случаев краев и локализации:

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

Ответ 15

В следующем коде используется сканирование char, поэтому нет регулярного выражения.

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/

Ответ 16

Здесь простая функция, которая вставляет запятые для тысяч разделителей. Он использует функции массива, а не 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

Ответ 17

Используйте этот код для обработки формата валюты для Индии. Код страны может быть изменен для обработки другой валюты страны.

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

// Use it.

formatter.format(amount);

выход:

3,50,256.95

Ответ 18

Я написал этот, прежде чем спотыкаться об этом посте. Нет регулярного выражения, и вы действительно можете понять код.

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

Ответ 19

Вы также можете использовать конструктор Intl.NumberFormat. Вот как вы можете это сделать.

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

Ответ 20

Для меня лучший ответ - использовать toLocaleString, как говорят некоторые участники. Если вы хотите включить символ '$', просто добавьте опции languaje и type. Вот и пример, чтобы отформатировать номер мексиканским песо

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

Ответ 21

Позвольте мне попытаться улучшить uKolka answer и, возможно, поможет другим сэкономить время.

Используйте 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>

Ответ 22

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

РЕДАКТИРОВАТЬ: функция работает только с положительным числом. для примера:

var number = -123123231232;
formatNumber(number)

Выход: "123,123,231,232"

Но чтобы ответить на вопрос выше, toLocaleString() просто решает проблему.

var number = 123123231232;
    number.toLocaleString()

Выход: "123,123,231,232"

Не унывайте!

Ответ 23

Я думаю, что эта функция позаботится обо всех проблемах, связанных с этой проблемой.

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

Ответ 24

Альтернативный способ, поддержка десятичных знаков, различных разделителей и негативов.

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.abs(Math.floor(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, не забудьте высказать его комментарий.

Ответ 25

Я добавил 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

Ответ 26

Уже много хороших ответов. Вот еще, просто для удовольствия:

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"

Ответ 27

Я думаю, что ваше решение является одним из более коротких, которые я видел для этого. Я не думаю, что есть стандартные функции JavaScript, чтобы делать такие вещи, поэтому вы, вероятно, сами по себе.

Я проверил спецификации CSS 3, чтобы увидеть, возможно ли это сделать в CSS, но если вы не хотите, чтобы каждая цифра была в своем собственном <span>, я не думаю, что это возможно.

Я нашел один проект Код Google, который выглядел многообещающим: flexible-js-formatting. Я не использовал его, но он выглядит довольно гибким и имеет модульные тесты, используя JsUnit. У разработчика также есть много сообщений (хотя и старых) об этой теме.

Обязательно рассмотрите международных пользователей: многие нации используют пространство в качестве разделителя и используют запятую для ветки десятичной дроби от неотъемлемой части числа.

Ответ 28

Решение из @user1437663 отлично.

Кто действительно понимает, что решение готово понимать сложные регулярные выражения.

Небольшое улучшение, чтобы сделать его более читаемым:

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

Шаблон начинается с \B, чтобы избежать использования запятой в начале слова. Интересно, что шаблон возвращается пустым, потому что \B не продвигает курсор (то же самое относится к $).

O \B сопровождается менее известными ресурсами, но является мощной функцией регулярных выражений Perl.

            Pattern1 (? = (Pattern2) ).

Магия заключается в том, что то, что находится в круглых скобках (Pattern2), является шаблоном, который следует за предыдущим шаблоном (Pattern1), но без продвижения курсора и также не является частью возвращаемого шаблона. Это своего рода будущая картина. Это похоже, когда кто-то смотрит вперед, но на самом деле не идет!

В этом случае pattern2 является

\d{3})+(?=$)

Это означает 3 цифры (один или несколько раз), за которыми следует конец строки ($)

Наконец, метод Заменить изменяет все вхождения найденного шаблона (пустая строка) для запятой. Это происходит только в случаях, когда оставшаяся часть кратна 3 цифрам (такие случаи, когда будущий курсор достигает конца начала координат).

Ответ 29

Просто для будущих Googlers (или не обязательно "Googlers"):

Все упомянутые выше решения замечательны, однако 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 no match & null 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

Используемое здесь регулярное выражение довольно просто, и цикл будет идти ровно столько раз, сколько потребуется для выполнения работы.

И вы могли бы оптимизировать его гораздо лучше, код "DRYify" и так далее.

Еще,

(-1234567.0987).toLocaleString();

(в большинстве ситуаций) будет гораздо лучшим выбором.

Дело не в скорости исполнения и не в кросс-браузерной совместимости.

В ситуациях, когда вы хотите показать полученное число пользователю, метод .toLocaleString() дает вам сверхспособность говорить на одном языке с пользователем вашего веб-сайта или приложения (независимо от того, какой у него язык).

Этот метод в соответствии с документацией ECMAScript был введен в 1999 году, и я полагаю, что причиной этого была надежда, что Интернет в какой-то момент соединит людей во всем мире, поэтому потребовались некоторые инструменты "интернализации".

Сегодня Интернет связывает нас всех, поэтому важно помнить, что мир намного сложнее, чем мы можем себе представить, и (/почти) все мы здесь, в Интернете.

Очевидно, что, учитывая разнообразие людей, невозможно гарантировать идеальный UX для всех, потому что мы говорим на разных языках, ценим разные вещи и т.д. И именно из-за этого еще более важно попытаться локализовать вещи настолько, насколько это возможно.,

Итак, учитывая, что существуют определенные стандарты для представления даты, времени, чисел и т.д. И что у нас есть инструмент для отображения этих вещей в формате, предпочитаемом конечным пользователем, это не так уж редко и почти безответственно использовать этот инструмент (особенно в ситуациях, когда мы хотим показать эти данные пользователю)?

Для меня использование RegExp вместо .toLocaleString() в подобной ситуации звучит немного похоже на создание приложения для часов с JavaScript и его жесткое программирование таким образом, чтобы оно отображало только пражское время (что было бы совершенно бесполезно для люди, которые не живут в Праге), хотя поведение по умолчанию

new Date();

вернуть данные в соответствии с конечными пользовательскими часами.

Ответ 30

Мое "настоящее" решение только для регулярных выражений для тех, кто любит однострочники

Вы видите тех восторженных игроков выше? Может быть, вы можете играть в гольф из этого. Вот мой удар.

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

ИспользуетТОНКОЕ ПРОСТРАНСТВО (U + 2009) для разделителя тысяч, как сказано в Международной системе единиц в восьмом издании (2006 г.) их публикации "Брошюра СИ: Международная система единиц (СИ)" (см. §5.3.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) { // Im 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);