Как напечатать число с запятой в качестве разделителя разрядов в 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, ",");
return x;
}
есть ли более простой или элегантный способ сделать это? Было бы неплохо, если бы он работал и с поплавками, но это не обязательно. Для выбора между периодами и запятыми не обязательно указывать конкретную локаль.
30 ответов
const numberWithCommas = (x) => {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
Это все, что вам действительно нужно знать.
@Neils Bom спросил, как работает регулярное выражение. Мое объяснение довольно длинное. Он не будет вписываться в комментарии, и я не знаю, куда еще его поместить, поэтому я делаю это здесь. Если у кого-то есть другие предложения о том, куда его поместить, пожалуйста, дайте мне знать.
в regex использует 2 утверждения lookahead: положительное, чтобы искать любую точку в строке, которая имеет несколько 3 цифр в строке после нее, и отрицательное утверждение, чтобы убедиться, что точка имеет только ровно несколько 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 цифр. Если это проблема, вы можете использовать эту функцию:
const numberWithCommas = (x) => {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
Я удивлен, что никто не упомянул количество.прототип.методом tolocalestring. Он реализован в JavaScript 1.5 (который был представлен в 1999 году), поэтому он в основном поддерживается в основных браузерах.
var n = 34523453.345
n.toLocaleString()
"34,523,453.345"
Он также работает в узле.js по состоянию на v0.12 через включение Intl
Если вы хотите что-то другое, цифра.js может быть интересно.
var number = 1234567890; // Example number to be converted
Mind имейте в виду, что 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 (сафари не поддерживается):
var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"
из того, что я проверил (Firefox, по крайней мере), они оба более или менее одинаковы в отношении производительности.
Я предлагаю использовать phpjs.org s 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, ",")
}
print(formatNumber(2665)); // 2,665
print(formatNumber(102665)); // 102,665
print(formatNumber(111102665)); // 111,102,665
спасибо всем за ответы. Я построил некоторые из ответов, чтобы сделать более "универсальное" решение.
первый фрагмент добавляет функцию, которая имитирует PHP ' s number_format()
к прототипу количество. Если я форматирую число, я обычно хочу десятичные знаки, поэтому функция принимает количество десятичных знаков для отображения. Некоторые страны используют запятые в качестве десятичных и десятичных знаков в качестве разделителя тысяч, поэтому функция позволяет этим разделителям будьте готовы.
Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';
var parts = this.toFixed(decimals).split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);
return parts.join(dec_point);
}
вы бы использовали это следующим образом:
var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00
я обнаружил, что мне часто нужно вернуть число для математических операций, но parseFloat преобразует 5,000 в 5, просто принимая первую последовательность целочисленных значений. Поэтому я создал свою собственную функцию преобразования float и добавил ее в прототип строки.
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
собственная функция 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
С помощью регулярного выражения
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: номер.прототип.методом 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>
Я думаю, что это самое короткое регулярное выражение, которое это делает:
/\B(?=(\d{3})+\b)/g
"123456".replace(/\B(?=(\d{3})+\b)/g, ",")
Я проверил его на нескольких числах, и это сработало.
Number.prototype.toLocaleString()
было бы здорово, если бы он был предоставлен изначально всеми браузерами (Safari).
Я проверил все остальные ответы, но никто, казалось, не заполнял его. Вот poc к тому, что на самом деле является комбинацией первых двух ответов; если toLocaleString
works он использует его, если он не использует пользовательскую функцию.
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));
Если вы имеете дело со значениями валюты и форматированием много, то, возможно, стоит добавить tiny Бухгалтерский учет.js который обрабатывает много пограничных случаев и локализации:
// Default usage:
accounting.formatMoney(12345678); // ,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
в следующем коде используется сканирование символов, поэтому регулярное выражение отсутствует.
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: незначительное исправление для решения проблемы, когда numhttps://jsfiddle.net/runsun/p5tqqvs3/
вы можете использовать эту процедуру для форматирования вашей валюты.
var nf = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
nf.format(123456.789); // ‘3,456.79’
для получения дополнительной информации, вы можете получить доступ к этой ссылке.
https://www.justinmccandless.com/post/formatting-currency-in-javascript/
вот простая функция, которая вставляет запятые для тысяч сепараторов. Он использует функции массива, а не регулярное выражение.
/**
* 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('');
};
Я написал это, прежде чем наткнуться на этот пост. Нет regex и вы действительно можете понять код.
$(function(){
function insertCommas(s) {
// get stuff before the dot
var d = s.indexOf('.');
var s2 = d === -1 ? s : s.slice(0, d);
// insert commas every 3 digits from the right
for (var i = s2.length - 3; i > 0; i -= 3)
s2 = s2.slice(0, i) + ',' + s2.slice(i);
// append fractional part
if (d !== -1)
s2 += s.slice(d);
return s2;
}
$('#theDudeAbides').text( insertCommas('1234567.89012' ) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="theDudeAbides"></div>
позвольте мне попытаться улучшить uKolka ' s ответ и может помочь другим сэкономить время.
использовать цифра.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>
вы должны пойти с количество.прототип.методом tolocalestring() только если его совместимость браузера - это не проблема.
для меня лучший ответ-использовать 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"})
Я думаю, что эта функция позаботится обо всех проблемах, связанных с этой проблемой.
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(".");
}
я добавил 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 это выглядело многообещающе: гибкий-Яш-форматирование. Я не использовал его, но он выглядит довольно гибким и имеет модульные тесты с использованием JsUnit. У разработчика также есть много сообщений (хотя и старых) по этой теме.
обязательно учитывайте международных пользователей: многие страны используют пробел в качестве разделителя и используют запятую для отделения десятичной дроби от неотъемлемой части числа.
много хороших ответов уже. Вот еще, просто для удовольствия:
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"
вот моя попытка:
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(/^.*(\..*)$/, '')
}
// 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)
Не найдя здесь современного и всеобъемлющего решения, я написал функцию стрелки (без регулярного выражения) для решения проблемы форматирования, и она позволяет вызывающему абоненту предоставить номер часть цифры а также срок и разделитель для Европы и остального мира.
примеры:
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. Если вход Нэн затем он просто возвращает его.
решение от @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 is
\d{3})+(?=$)
это означает 3 цифры (один или несколько раз), за которыми следует конец строки ($)
наконец, заменить метод изменяет все вхождения найденного шаблона (пустая строка) для запятой. Это происходит только в тех случаях, когда оставшаяся часть делится на 3 цифры (такие случаи, когда будущий курсор достигает конца источника).
вот хорошее решение с меньшим количеством кодирования...
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 += ",";
}
альтернативный способ, поддерживающий десятичные дроби, различные сепараторы и негативы.
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;
}
я адаптировал ваш код для работы в текстовом поле (Тип ввода="текст"), чтобы мы могли вводить и удалять цифры в режиме реального времени без потери курсора. Это работает также, если вы выбираете range при удалении. И вы можете использовать стрелки и кнопки 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);"/>