Как напечатать число с запятыми как разделители тысяч в 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);