Я пытаюсь напечатать целое число в 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;
}
Есть ли более простой или элегантный способ сделать это? Было бы неплохо, если бы он работал с поплавками, но это не обязательно. Для принятия решения между периодами и запятыми не обязательно быть языковым.
Я использовал идею из ответа Керри, но упростил ее, так как я просто искал что-то простое для моей конкретной цели. Вот что я сделал:
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(".");
}
Я удивлен, что никто не упомянул Number.prototype.toLocaleString. Он реализован в JavaScript 1.5 (который был представлен в 1999 году), поэтому он в основном поддерживается во всех основных браузерах.
var n = 34523453.345
n.toLocaleString()
"34,523,453.345"
Это также работает в Node.js с v0.12 через включение Intl
Просто обратите внимание, что эта функция возвращает строку, а не число
Если вы хотите что-то другое, Numeral.js может быть интересным.
var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00"
Эти опции не работают в FF или Safari.
var number = 1234567890; // Example number to be converted
Помните, что javascript имеет максимальное целое число 9007199254740991
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), они более или менее похожи на производительность.
Я предлагаю использовать 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;
}
Это вариация ответа @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] : "");
}
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
Использование регулярного выражения
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"
ДЕМО НА ЗДЕСЬ
<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>
Спектакль
Нативная функция 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
Спасибо всем за их ответы. Я отработал некоторые ответы, чтобы сделать более "одноразовое решение".
Первый фрагмент добавляет функцию, которая подражает 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
var parts = this.toFixed(decimals).toString().split('.');
var dec_point
. Спасибо что подметил это.
Я думаю, что это кратчайшее регулярное выражение, которое делает это:
/\B(?=(\d{3})+\b)/g
"123456".replace(/\B(?=(\d{3})+\b)/g, ",")
Я проверил его на несколько цифр, и он сработал.
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));
0.12345
будет выдавать 0.12,345
. Хорошая реализация для этого может быть найдена в underscore.string
value > 1000
в условие if, исправляет этот случай, однако это был случай, и, конечно, лучше проверенные версии можно найти в другом месте, спасибо за указание.
Разделитель тысяч может быть вставлен в международном режиме с использованием объекта 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, похоже, не имеет временной шкалы для реализации.
Вы можете использовать эту процедуру для форматирования необходимой валюты.
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/
если вы имеете дело с валютными ценностями и форматированием, то может быть стоит добавить маленький 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
В следующем коде используется сканирование 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/
commafy(-123456)
это дает -,123,456
Здесь простая функция, которая вставляет запятые для тысяч разделителей. Он использует функции массива, а не 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
Я написал этот, прежде чем спотыкаться об этом посте. Нет регулярного выражения, и вы действительно можете понять код.
$(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>
Для меня лучший ответ - использовать toLocaleString, как говорят некоторые участники. Если вы хотите включить символ '$', просто добавьте опции languaje и type. Вот и пример, чтобы отформатировать номер мексиканским песо
var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))
Ярлык
1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})
Позвольте мне попытаться улучшить 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>
Вы должны пойти с Number.prototype.toLocaleString(), только если его browser compatibilty не является проблемой.
Я думаю, что эта функция позаботится обо всех проблемах, связанных с этой проблемой.
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;
}
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)
Выход: "1 000 000 000,00"
Но чтобы ответить на вопрос выше, toLocaleString()
просто решает проблему.
var number = -123123231232;
number.toLocaleString()
Выход: "-123, 123,231,232"
Не унывайте!
Я нашел подход, который работает в любой ситуации. Пример CodeSandbox
function commas(n) {
if (n < 1000) {
return n + ''
} else {
// Convert to string.
n += ''
// Skip scientific notation.
if (n.indexOf('e') !== -1) {
return n
}
// Support fractions.
let i = n.indexOf('.')
let f = i == -1 ? '' : n.slice(i)
if (f) n = n.slice(0, i)
// Add commas.
i = n.length
n = n.split('')
while (i > 3) n.splice((i -= 3), 0, ',')
return n.join('') + f
}
}
Это похоже на ответ Ноа Фрейтаса, но с поддержкой дробей и научных обозначений.
Я думаю, что toLocaleString
- лучший выбор, если производительность не является проблемой.
редактировать: здесь CodeSandbox с некоторыми примерами: https://codesandbox.io/s/zmvxjpj6x
commas(12345.67)
и получил «12 345,6700000000000728».
Не найдя здесь современного и всеобъемлющего решения, я написал функцию стрелки (без регулярного выражения), чтобы решить проблему форматирования, и она позволяет вызывающему абоненту предоставить количество цифр разряда, а также период и тысячу разделителей для Европы и остальных Мир.
Примеры:
numberFormatter(1234567890.123456) => 1,234,567,890 numberFormatter(1234567890.123456, 4) => 1,234,567,890.1235 numberFormatter(1234567890.123456, 4, '.', ',') => 1.234.567.890,1235 Europe
Вот функция, написанная в ES6 (современный синтаксис):
const numberFormatter = (number, fractionDigits = 0, thousandSeperator = ',', fractionSeperator = '.') => {
if (number!==0 && !number || !Number.isFinite(number)) return number
const frDigits = Number.isFinite(fractionDigits)? Math.min(Math.max(fractionDigits, 0), 7) : 0
const num = number.toFixed(frDigits).toString()
const parts = num.split('.')
let digits = parts[0].split('').reverse()
let sign = ''
if (num < 0) {sign = digits.pop()}
let final = []
let pos = 0
while (digits.length > 1) {
final.push(digits.shift())
pos++
if (pos % 3 === 0) {final.push(thousandSeperator)}
}
final.push(digits.shift())
return '${sign}${final.reverse().join('')}${frDigits > 0 ? fractionSeperator : ''}${frDigits > 0 && parts[1] ? parts[1] : ''}'
}
Он был протестирован на случаи отрицательного, плохого ввода и NaN. Если вход NaN, он просто возвращает его.
Вот одна строка с поддержкой int и decimal. Я также оставил код для преобразования числа в строку.
function numberWithCommas(x) {
return (x=x+'').replace(new RegExp('\\B(?=(\\d{3})+'+(~x.indexOf('.')?'\\.':'$')+')','g'),',');
}
Здесь моя попытка:
EDIT: добавлено в десятичные знаки
function splitMille(n, separator = ',') {
// Cast to string
let num = (n + '')
// Test for and get any decimals (the later operations won't support them)
let decimals = ''
if (/\./.test(num)) {
// This regex grabs the decimal point as well as the decimal numbers
decimals = num.replace(/^.*(\..*)$/, '$1')
}
// Remove decimals from the number string
num = num.replace(decimals, '')
// Reverse the number string through Array functions
.split('').reverse().join('')
// Split into groups of 1-3 characters (with optional supported character "-" for negative numbers)
.match(/[0-9]{1,3}-?/g)
// Add in the mille separator character and reverse back
.join(separator).split('').reverse().join('')
// Put the decimals back and output the formatted number
return `${num}${decimals}`
}
let testA = splitMille(1234)
let testB = splitMille(-1234)
let testC = splitMille(123456.789)
let testD = splitMille(9007199254740991)
let testE = splitMille(1000.0001)
console.log('Results!\n\tA: %s\n\tB: %s\n\tC: %s\n\tD: %s\n\tE: %s', testA, testB, testC, testD, testE)
Если вы используете AngularJS, этот фильтр валюты может определенно помочь: http://www.w3schools.com/angular/ng_filter_currency.asp
Я адаптировал ваш код для работы в TextBox (Input type = "text" ), чтобы мы могли вводить и удалять цифры в реальном времени без потери курсора. Он также работает, если вы выбираете диапазон при удалении. И вы можете свободно использовать стрелки и кнопки home/end.
Спасибо, что сэкономили мое время!
//function controls number format as "1,532,162.3264321"
function numberWithCommas(x) {
var e = e || window.event;
if (e.keyCode >= '35' && e.keyCode <= '40') return; //skip arrow-keys
var selStart = x.selectionStart, selEnd = x.selectionEnd; //save cursor positions
var parts = x.value.toString().split(".");
var part0len = parts[0].length; //old length to check if new ',' would be added. Need for correcting new cursor position (+1 to right).
//if user deleted ',' - remove previous number instead (without selection)
if (x.selectionLength == 0 && (e.keyCode == 8 || e.keyCode == 46)) {//if pressed 8-backspace or 46-delete button
var delPos = parts[0].search(/\d{4}/);
if (delPos != -1) {//if found 4 digits in a row (',' is deleted)
if (e.keyCode == 8) {//if backspace flag
parts[0] = parts[0].slice(0, selStart - 1) + parts[0].slice(selEnd, parts[0].length);
selEnd--;
if (selStart > selEnd) selStart = selEnd;
} else {
parts[0] = parts[0].slice(0, selStart) + parts[0].slice(selEnd + 1, parts[0].length);
selStart++;
if (selEnd < selStart) selEnd = selStart;
}
}
}
var hasMinus = parts[0][0] == '-';
parts[0] = (hasMinus ? '-' : '') + parts[0].replace(/[^\d]*/g, ""); //I'd like to clear old ',' to avoid things like 1,2,3,5,634.443216
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); //sets ',' between each 3 digits
if (part0len < parts[0].length) { //move cursor to right if added new ','
selStart++;
selEnd++;
} else if (part0len > parts[0].length) { //..or if removed last one ','
selStart--;
selEnd--;
}
x.value = parts.join(".");
x.setSelectionRange(selStart, selEnd); //restoring cursor position
}
function saveSelectionLength(x) {
x.selectionLength = x.selectionEnd - x.selectionStart;
}
Чтобы использовать это только что добавленные два события - onKeyUp и onKeyDown
<asp:TextBox runat="server" ID="val" Width="180px" onKeyUp="numberWithCommas(this);" onKeyDown="saveSelectionLength(this);"/>
Уже много хороших ответов. Вот еще, просто для удовольствия:
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
Я добавил 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
Я думаю, что ваше решение является одним из более коротких, которые я видел для этого. Я не думаю, что есть стандартные функции JavaScript, чтобы делать такие вещи, поэтому вы, вероятно, сами по себе.
Я проверил спецификации CSS 3, чтобы увидеть, возможно ли это сделать в CSS, но если вы не хотите, чтобы каждая цифра была в своем собственном <span>
, я не думаю, что это возможно.
Я нашел один проект Код Google, который выглядел многообещающим: flexible-js-formatting. Я не использовал его, но он выглядит довольно гибким и имеет модульные тесты, используя JsUnit. У разработчика также есть много сообщений (хотя и старых) об этой теме.
Обязательно рассмотрите международных пользователей: многие нации используют пространство в качестве разделителя и используют запятую для ветки десятичной дроби от неотъемлемой части числа.
Вы можете использовать библиотеку D3 для этого, и это делает номера форматирования очень легкими.
используйте <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
в HTML <head>
и вам нужно просто:
var formatThousandsSeparator = function(d) { return d3.format(",d") (d); };
formatThousandsSeparator(your_number);
Вот некоторая документация по большему количеству способов использования форматирования D3
Я думал, что поделюсь небольшим трюком, который я использую для форматирования большого числа. Вместо того, чтобы вставлять запятые или пробелы, я вставляю пустой, но видимый промежуток между "тысячами". Это делает тысячи легко видимыми, но позволяет копировать/вставлять ввод в исходном формате без запятых/пробелов.
// This function accepts an integer, and produces a piece of HTML that shows it nicely with
// some empty space at "thousand" markers.
// Note, these space are not spaces, if you copy paste, they will not be visible.
function valPrettyPrint(orgVal) {
// Save after-comma text, if present
var period = orgVal.indexOf(".");
var frac = period >= 0 ? orgVal.substr(period) : "";
// Work on input as an integer
var val = "" + Math.trunc(orgVal);
var res = "";
while (val.length > 0) {
res = val.substr(Math.max(0, val.length - 3), 3) + res;
val = val.substr(0, val.length - 3);
if (val.length > 0) {
res = "<span class='thousandsSeparator'></span>" + res;
}
}
// Add the saved after-period information
res += frac;
return res;
}
С помощью этого CSS:
.thousandsSeparator {
display : inline;
padding-left : 4px;
}
См. пример JSFiddle.
.thousandsSeparator:before{ content: ','; }
JSFiddle: jsfiddle.net/Dandalf/ze6agw7v
При форматировании специфических для локали сообщений, таких как форматирование чисел. Используйте инструмент интернационализации. Сложность форматирования чисел значительно увеличивается, так как вы добавляете больше локалей. Поэтому не форматируйте числовое форматирование. Потому что обслуживание будет затруднено через некоторое время.
Я использую инструмент l10ns (http://l10ns.org). Это инструмент интернационализации для javascript и предварительная компиляция форматированных сообщений для вас.
var l = requireLocalizations('en-US');
var string = l('NUMBER_OF_LIKES', {
likes: 1100
});
console.log(string) // outputs 1,100
Теперь определите формат сообщения.
{likes, number, integer}
Если вы хотите получить фантазию и использовать плюрализации.
{likes, plural, one{# like} other {# likes}}
Подробнее о плюрализации. Пожалуйста, проверьте их docs.
Альтернативный способ, поддерживающий десятичные знаки, различные разделители и негативы.
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.ceil(number)).toString()
, i = n.length % 3
, f = n.substr(0, i)
;
if(number < 0) f = '-' + f;
for(;i<n.length;i+=3) {
if(i!=0) f+=ts;
f+=n.substr(i,3);
}
if(dp > 0)
f += ds + number.toFixed(dp).split('.')[1]
return f;
}
Мне нужно было что-то простое, что было легко читать. Меня интересуют только целые числа, и мне не нужна высокая производительность (поэтому оптимизация для чтения по производительности):
function numberWithCommas(number) {
if (isNaN(number)) {
return '';
}
var asString = '' + Math.abs(number),
numberOfUpToThreeCharSubstrings = Math.ceil(asString.length / 3),
startingLength = asString.length % 3,
substrings = [],
isNegative = (number < 0),
formattedNumber,
i;
if (startingLength > 0) {
substrings.push(asString.substring(0, startingLength));
}
for (i=startingLength; i < asString.length; i += 3) {
substrings.push(asString.substr(i, 3));
}
formattedNumber = substrings.join(',');
if (isNegative) {
formattedNumber = '-' + formattedNumber;
}
return formattedNumber;
}
JSFiddle: http://jsfiddle.net/Enw85/1/
Вот хорошее решение с меньшим количеством кодирования...
var y = "";
var arr = x.toString().split("");
for(var i=0; i<arr.length; i++)
{
y += arr[i];
if((arr.length-i-1)%3==0 && i<arr.length-1) y += ",";
}
-123456
это дает -1,234,56
Решение из @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 цифрам (такие случаи, когда будущий курсор достигает конца начала координат).
function addCommas(nStr) {
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
addCommas(parseFloat("1099920.23232").toFixed(2)); //Output 1,099,920.23
Для целых чисел я использовал очень простой метод:
var myNumber = 99999,
myString = myNumber + "";
myString.length > 3 ? return myString.substring(0, myString.length - 3) + "," +
myString.substring(myString.length - 3) : return myString;
return
s, вместо этого выполните: return myString.length > 3 ? myString.substring(0, myString.length - 3) + "," + myString.substring(myString.length - 3) : myString;
Вы можете использовать для циклов, чтобы добавить запятые к числу
function convertNumber(){
var _cash = cash.toString()
var _formattedCash = ''
var count = 0
for (let i = _cash.length; i >= 0; i--) {
_formattedCash += _cash.substring(i,i+1)
if(count == 3 && i > 0){
_formattedCash += ','
count = 0
}
count++
}
var _format = ''
for (let i = _formattedCash.length; i >= 0; i--) {
_format += _formattedCash.substring(i, i + 1)
}
return 'Ksh ' + _format;
}
cash
. И что означает 'Ksh '
в операторе возврата?
Теперь это должно работать... отредактировано для добавления десятичных знаков, если число является десятичным.
<script>
function makedollars(mynumber)
{
mynumber = mynumber.toString();
var numberend="";
if(mynumber.split('.').length>1){
var mynumbersplit = mynumber.split('.');
mynumber = mynumbersplit[0];
numberend= mynumbersplit[1];
}
var mn = mynumber.length;
if (mn <= 3) { return mynumber + numberend; }
var grps = [];
while (mn > 3)
{
grps.push(mynumber.substring(mn,mn - 3));
mn = mn - 3;
}
grps.push(mynumber.substring(mn,mn - 3));
grps.reverse();
grps.join(",");
if(numberend!=""){ grps = grps +"."+numberend;}
return grps;
}
</script>
makedollars(12345.67)
и получил массив строк: ["12", "345.67", ".67"]
.
Для индийской числовой системы
var number = "323483.85"
var decimal = number.split(".");
var res = (decimal[0].length>3? numberWithCommas(decimal[0].substring(0,decimal[0].length-3))+ ',' :decimal[0]) + (decimal[0].length>3?decimal[0].substring(decimal[0].length-3,decimal[0].length):'') + '.' + decimal[1];
Выход: 3,23,483.85
Еще один.. (для int, как задает вопрос)
function insertCommas(str)
{
var a = str.split("");
a.reverse();
var t, i = 0, arr = Array();
while (t = a.shift())
{
if (((i++ % 3) == 0) && arr.length > 0)
arr.unshift(",");
arr.unshift(t);
}
return arr.join("");
}
Вы можете просто использовать printf
-way, например:
double number = 1234567;
System.out.printf("%,.2f" , number);