Я хотел бы отформатировать цену в JavaScript.
Мне нужна функция, которая принимает float
в качестве аргумента и возвращает формат string
следующим образом:
"$ 2,500.00"
Какой лучший способ сделать это?
Я хотел бы отформатировать цену в JavaScript.
Мне нужна функция, которая принимает float
в качестве аргумента и возвращает формат string
следующим образом:
"$ 2,500.00"
Какой лучший способ сделать это?
Хорошо, основываясь на том, что вы сказали, я использую это:
var DecimalSeparator = Number("1.2").toLocaleString().substr(1,1);
var AmountWithCommas = Amount.toLocaleString();
var arParts = String(AmountWithCommas).split(DecimalSeparator);
var intPart = arParts[0];
var decPart = (arParts.length > 1 ? arParts[1] : '');
decPart = (decPart + '00').substr(0,2);
return '£ ' + intPart + DecimalSeparator + decPart;
Я открыт для предложений по улучшению (я бы предпочел не включать YUI только для этого:-)) Я уже знаю, что должен обнаруживать "." вместо того, чтобы просто использовать его как десятичный разделитель...
Это решение совместимо с любым основным браузером:
const profits = 2489.8237;
profits.toFixed(3) //returns 2489.824 (rounds up)
profits.toFixed(2) //returns 2489.82
profits.toFixed(7) //returns 2489.8237000 (pads the decimals)
Все, что вам нужно, это добавить символ валюты (например, "$" + profits.toFixed(2)
), и вы получите свою сумму в долларах.
Если вам требуется использовать ,
между каждой цифрой, вы можете использовать эту функцию:
function formatMoney(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;
return sign +
(j ? i.substr(0, j) + thouSep : "") +
i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "$1" + thouSep) +
(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}
document.getElementById("b").addEventListener("click", event => {
document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>
(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // 12,345.67
Идея этого решения заключается в замене согласованных разделов первым совпадением и запятой, то есть '$&,'
. Согласование выполняется с использованием метода lookahead. Вы можете прочитать выражение как "соответствовать числу, если за ним следует последовательность из трех наборов чисел (одна или несколько) и точка".
ИСПЫТАНИЯ:
1 --> "1.00"
12 --> "12.00"
123 --> "123.00"
1234 --> "1,234.00"
12345 --> "12,345.00"
123456 --> "123,456.00"
1234567 --> "1,234,567.00"
12345.67 --> "12,345.67"
ДЕМО: http://jsfiddle.net/hAfMM/9571/
Вы также можете расширить прототип объекта Number
чтобы добавить дополнительную поддержку любого количества десятичных знаков [0.. n]
и размера групп чисел [0.. x]
:
/**
* Number.prototype.format(n, x)
*
* @param integer n: length of decimal
* @param integer x: length of sections
*/
Number.prototype.format = function(n, x) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};
1234..format(); // "1,234"
12345..format(2); // "12,345.00"
123456.7.format(3, 2); // "12,34,56.700"
123456.789.format(2, 4); // "12,3456.79"
ДЕМО/ИСПЫТАНИЯ: http://jsfiddle.net/hAfMM/435/
В этой расширенной версии вы можете установить разные типы разделителей:
/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed s: sections delimiter
* @param mixed c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
num = this.toFixed(Math.max(0, ~~n));
return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};
12345678.9.format(2, 3, '.', ','); // "12.345.678,90"
123456.789.format(4, 4, ' ', ':'); // "12 3456:7890"
12345678.9.format(0, 3, '-'); // "12-345-679"
ДЕМО/ИСПЫТАНИЯ: http://jsfiddle.net/hAfMM/612/
В Javascript есть средство форматирования чисел (часть API интернационализации).
// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
});
formatter.format(2500); /* $2,500.00 */
Используйте undefined
вместо первого аргумента (в примере 'en-US'
), чтобы использовать языковой стандарт системы (языковой стандарт пользователя в случае, если код выполняется в браузере).
Последнее замечание, сравнивающее это со старым. toLocaleString
. Они оба предлагают по существу одинаковую функциональность. Однако toLocaleString в его более старых версиях (pre-Intl) на самом деле не поддерживает локали: он использует локаль системы. Поэтому убедитесь, что вы используете правильную версию (MDN предлагает проверить наличие Intl
). Кроме того, производительность обоих одинакова для одного элемента, но если у вас много чисел для форматирования, использование Intl.NumberFormat
в ~ 70 раз быстрее. Вот как использовать toLocaleString
:
(2500).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
}); /* $2,500.00 */
Взгляните на объект JavaScript Number и посмотрите, может ли он вам помочь.
toLocaleString()
будет отформатировать число, используя разделитель тысяч тысяч адресов.toFixed()
будет округлять число до определенного числа десятичных знаков.Чтобы использовать их одновременно, значение должно иметь свой тип, измененный обратно на число, потому что они оба выводят строку.
Пример:
Number(someNumber.toFixed(1)).toLocaleString()
Ниже приведен код Патрика Дежарденса (псевдоним Daok) с небольшим количеством добавленных комментариев и некоторыми незначительными изменениями:
/*
decimal_sep: character used as deciaml separtor, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{
var n = this,
c = isNaN(decimals) ? 2 : Math.abs(decimals), //if decimal is zero we must take it, it means user does not want to show any decimal
d = decimal_sep || '.', //if no decimal separator is passed we use the dot as default decimal separator (we MUST use a decimal separator)
/*
according to [/questions/3130/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
the fastest way to check for not defined parameter is to use typeof value === 'undefined'
rather than doing value === undefined.
*/
t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, //if you don't want to use a thousands separator you can pass empty string as thousands_sep value
sign = (n < 0) ? '-' : '',
//extracting the absolute value of the integer part of the number and converting to string
i = parseInt(n = Math.abs(n).toFixed(c)) + '',
j = ((j = i.length) > 3) ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
}
и вот несколько тестов:
//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());
//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));
Незначительные изменения:
Немного переместил Math.abs(decimals)
, чтобы сделать только тогда, когда нет NaN
.
decimal_sep
больше не может быть пустой строкой (НЕОБХОДИМО какой-то десятичный разделитель)
мы используем typeof thousands_sep === 'undefined'
, как предложено в Как лучше всего определить, не передан ли аргумент в функцию JavaScript
(+n || 0)
не требуется, поскольку this
является объектом Number
accounting.js - это крошечная библиотека JavaScript для форматирования чисел, денег и валюты.
Если количество - это число, скажем -123
, тогда
amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
"-$123.00"
строку "-$123.00"
.
Вот полный рабочий пример.
Здесь лучший форматировщик js money, который я видел:
Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
var n = this,
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSeparator = decSeparator == undefined ? "." : decSeparator,
thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
sign = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
Он был переформатирован и заимствован отсюда: fooobar.com/questions/1119/...
Вам нужно будет указать свой собственный валютный указатель (вы использовали $выше).
Назовите его так (хотя обратите внимание, что аргументы по умолчанию равны 2, запятой и периоду, поэтому вам не нужно указывать какие-либо аргументы, если вы предпочитаете):
var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"
Здесь уже есть отличные ответы. Вот еще одна попытка, просто для удовольствия:
function formatDollar(num) {
var p = num.toFixed(2).split(".");
return "$" + p[0].split("").reverse().reduce(function(acc, num, i, orig) {
return num=="-" ? acc : num + (i && !(i % 3) ? "," : "") + acc;
}, "") + "." + p[1];
}
И некоторые тесты:
formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"
Отредактировано: теперь он будет обрабатывать и отрицательные числа
Я думаю, что вы хотите f.nettotal.value = "$" + showValue.toFixed(2);
Работает для всех текущих браузеров
Используйте toLocaleString
для форматирования валюты в ее чувствительном к языку представлении (используя ISO 4217 коды валют).
(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})
Пример фрагментов кода южноафриканского рэнда для @avenmore
console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00
Numeral.js - библиотека js для легкого форматирования чисел от @adamwdraper
numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
Я использую библиотеку Globalize (от Microsoft):
Это отличный проект для локализации чисел, валют и дат и автоматического их форматирования в соответствии с пользовательским языком!... и, несмотря на это, должно быть расширение jQuery, в настоящее время это 100% независимая библиотека. Я предлагаю вам все попробовать!:)
javascript-number-formatter (ранее в Google Code)
-000.####
форматирование, такое как #,##0.00
или с отрицанием -000.####
.# ##0,00
, #,###.##
, #'###.##
или любой тип не нумерованного символа.#,##,#0.000
или #,###0.##
все действительны.##,###,##.#
или 0#,#00#.###0#
все в порядке.format( "0.0000", 3.141592)
.(отрывок из его README)
Существует javascript-порт функции PHP "number_format".
Я нахожу его очень полезным, поскольку он прост в использовании и узнаваем для разработчиков PHP.
function number_format (number, decimals, dec_point, thousands_sep) {
var n = number, prec = decimals;
var toFixedFix = function (n,prec) {
var k = Math.pow(10,prec);
return (Math.round(n*k)/k).toString();
};
n = !isFinite(+n) ? 0 : +n;
prec = !isFinite(+prec) ? 0 : Math.abs(prec);
var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;
var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec);
//fix for IE parseFloat(0.55).toFixed(0) = 0;
var abs = toFixedFix(Math.abs(n), prec);
var _, i;
if (abs >= 1000) {
_ = abs.split(/\D/);
i = _[0].length % 3 || 3;
_[0] = s.slice(0,i + (n < 0)) +
_[0].slice(i).replace(/(\d{3})/g, sep+'$1');
s = _.join(dec);
} else {
s = s.replace('.', dec);
}
var decPos = s.indexOf(dec);
if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
}
else if (prec >= 1 && decPos === -1) {
s += dec+new Array(prec).join(0)+'0';
}
return s;
}
(блок комментариев из оригинал, приведенный ниже для примеров и кредитов, где это необходимо)
// Formats a number with grouped thousands
//
// version: 906.1806
// discuss at: http://phpjs.org/functions/number_format
// + 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)
// * 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'
+1 к Jonathan M для предоставления исходного метода. Так как это явно форматирование валюты, я пошел вперед и добавил символ валюты (по умолчанию "$" ) к выходу и добавил запятую по умолчанию в качестве разделителя тысяч. Если вам действительно не нужен символ валюты (или разделитель тысяч), просто используйте "" (пустую строку) в качестве аргумента для него.
Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
// check the args and supply defaults:
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator == undefined ? "." : decSeparator;
thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;
var n = this,
sign = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return sign + currencySymbol + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
Более короткий метод (для вставки пробела, запятой или точкой) с регулярным выражением?
Number.prototype.toCurrencyString=function(){
return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g,'$1 ');
}
n=12345678.9;
alert(n.toCurrencyString());
Patrick Desjardins ответ выглядит хорошо, но я предпочитаю, чтобы мой javascript был прост. Здесь функция, которую я только что написал, чтобы взять число и вернуть его в формате валюты (минус знак доллара)
// Format numbers to two decimals with commas
function formatDollar(num) {
var p = num.toFixed(2).split(".");
var chars = p[0].split("").reverse();
var newstr = '';
var count = 0;
for (x in chars) {
count++;
if(count%3 == 1 && count != 1) {
newstr = chars[x] + ',' + newstr;
} else {
newstr = chars[x] + newstr;
}
}
return newstr + "." + p[1];
}
Существует встроенный function
toFixed в javascript
var num = new Number(349);
document.write("$" + num.toFixed(2));
Не видел этого. Это довольно лаконично и легко понять.
function moneyFormat(price, sign = '$') {
const pieces = parseFloat(price).toFixed(2).split('')
let ii = pieces.length - 3
while ((ii-=3) > 0) {
pieces.splice(ii, 0, ',')
}
return sign + pieces.join('')
}
console.log(
moneyFormat(100),
moneyFormat(1000),
moneyFormat(10000.00),
moneyFormat(1000000000000000000)
)
Основная часть - вставка тысяч разделителей, что можно сделать следующим образом:
<script type="text/javascript">
function ins1000Sep(val){
val = val.split(".");
val[0] = val[0].split("").reverse().join("");
val[0] = val[0].replace(/(\d{3})/g,"$1,");
val[0] = val[0].split("").reverse().join("");
val[0] = val[0].indexOf(",")==0?val[0].substring(1):val[0];
return val.join(".");
}
function rem1000Sep(val){
return val.replace(/,/g,"");
}
function formatNum(val){
val = Math.round(val*100)/100;
val = (""+val).indexOf(".")>-1 ? val + "00" : val + ".00";
var dec = val.indexOf(".");
return dec == val.length-3 || dec == 0 ? val : val.substring(0,dec+3);
}
</script>
<button onclick="alert(ins1000Sep(formatNum(12313231)));">
Я предлагаю класс NumberFormat из API визуализации Google.
Вы можете сделать что-то вроде этого:
var formatter = new google.visualization.NumberFormat({
prefix: '$',
pattern: '#,###,###.##'
});
formatter.formatValue(1000000); // $ 1,000,000
Надеюсь, это поможет.
function CurrencyFormatted(amount)
{
var i = parseFloat(amount);
if(isNaN(i)) { i = 0.00; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
i = parseInt((i + .005) * 100);
i = i / 100;
s = new String(i);
if(s.indexOf('.') < 0) { s += '.00'; }
if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
s = minus + s;
return s;
}
Из WillMaster.
Это может быть немного поздно, но вот метод, который я только что обработал для коллеги, чтобы добавить функцию .toCurrencyString()
, поддерживающую локали, ко всем номерам. Интернализация предназначена только для группировки чисел, а не знака валюты - если вы выставляете доллары, используйте "$"
как указано, потому что $123 4567
в Японии или Китае такое же количество долларов США, что и $1,234,567
здесь, в США, Если вы выставляете евро/и т.д., Измените знак валюты с "$"
.
Объявляйте это в любом месте своего HEAD или там, где это необходимо, непосредственно перед его использованием:
Number.prototype.toCurrencyString = function(prefix, suffix) {
if (typeof prefix === 'undefined') { prefix = '$'; }
if (typeof suffix === 'undefined') { suffix = ''; }
var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
}
Тогда все готово! Используйте (number).toCurrencyString()
где угодно, чтобы вывести номер в качестве валюты.
var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
Как обычно, существует несколько способов сделать одно и то же, но я бы избегал использования Number.prototype.toLocaleString
, так как он может возвращать разные значения на основе пользовательских настроек.
Я также не рекомендую распространять прототипы собственных прототипов Number.prototype
- это плохая практика, поскольку это может вызвать конфликты с кодом других людей (например, библиотеки/фреймворки/плагины) и может быть несовместимо с будущими реализациями JavaScript/версии.
Я считаю, что регулярные выражения - лучший подход к проблеме, вот моя реализация:
/**
* Converts number into currency format
* @param {number} number Number that should be converted.
* @param {string} [decimalSeparator] Decimal separator, defaults to '.'.
* @param {string} [thousandsSeparator] Thousands separator, defaults to ','.
* @param {int} [nDecimalDigits] Number of decimal digits, defaults to `2`.
* @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
*/
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
//default values
decimalSeparator = decimalSeparator || '.';
thousandsSeparator = thousandsSeparator || ',';
nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;
var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]
if(parts){ //number >= 1000 || number <= -1000
return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
}else{
return fixed.replace('.', decimalSeparator);
}
}
отредактировано в 2010/08/30: добавлена опция для установки числа десятичных цифр. отредактированный в 2011/08/23: добавлена возможность установить число десятичных цифр в ноль.
Вот некоторые решения: все передают набор тестов, набор тестов и контрольный тест, если вы хотите скопировать и вставить для тестирования, попробуйте This Gist.
База на fooobar.com/questions/1119/..., но исправить, если нет десятичной точки.
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.');
a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
return a.join('.');
}
}
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.'),
// skip the '-' sign
head = Number(this < 0);
// skip the digits that before the first thousands separator
head += (a[0].length - head) % 3 || 3;
a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
return a.join('.');
};
}
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.');
a[0] = a[0]
.split('').reverse().join('')
.replace(/\d{3}(?=\d)/g, '$&,')
.split('').reverse().join('');
return a.join('.');
};
}
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('');
a.push('.');
var i = a.indexOf('.') - 3;
while (i > 0 && a[i-1] !== '-') {
a.splice(i, 0, ',');
i -= 3;
}
a.pop();
return a.join('');
};
}
console.log('======== Demo ========')
console.log(
(1234567).format(0),
(1234.56).format(2),
(-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
n = (n * 10) + (i % 10)/100;
console.log(n.format(2), (-n).format(2));
}
Если мы хотим использовать разделитель разделителей тысяч или десятичный разделитель, используйте replace()
:
123456.78.format(2).replace(',', ' ').replace('.', ' ');
function assertEqual(a, b) {
if (a !== b) {
throw a + ' !== ' + b;
}
}
function test(format_function) {
console.log(format_function);
assertEqual('NaN', format_function.call(NaN, 0))
assertEqual('Infinity', format_function.call(Infinity, 0))
assertEqual('-Infinity', format_function.call(-Infinity, 0))
assertEqual('0', format_function.call(0, 0))
assertEqual('0.00', format_function.call(0, 2))
assertEqual('1', format_function.call(1, 0))
assertEqual('-1', format_function.call(-1, 0))
// decimal padding
assertEqual('1.00', format_function.call(1, 2))
assertEqual('-1.00', format_function.call(-1, 2))
// decimal rounding
assertEqual('0.12', format_function.call(0.123456, 2))
assertEqual('0.1235', format_function.call(0.123456, 4))
assertEqual('-0.12', format_function.call(-0.123456, 2))
assertEqual('-0.1235', format_function.call(-0.123456, 4))
// thousands separator
assertEqual('1,234', format_function.call(1234.123456, 0))
assertEqual('12,345', format_function.call(12345.123456, 0))
assertEqual('123,456', format_function.call(123456.123456, 0))
assertEqual('1,234,567', format_function.call(1234567.123456, 0))
assertEqual('12,345,678', format_function.call(12345678.123456, 0))
assertEqual('123,456,789', format_function.call(123456789.123456, 0))
assertEqual('-1,234', format_function.call(-1234.123456, 0))
assertEqual('-12,345', format_function.call(-12345.123456, 0))
assertEqual('-123,456', format_function.call(-123456.123456, 0))
assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
// thousands separator and decimal
assertEqual('1,234.12', format_function.call(1234.123456, 2))
assertEqual('12,345.12', format_function.call(12345.123456, 2))
assertEqual('123,456.12', format_function.call(123456.123456, 2))
assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}
console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);
function benchmark(f) {
var start = new Date().getTime();
f();
return new Date().getTime() - start;
}
function benchmark_format(f) {
console.log(f);
time = benchmark(function () {
for (var i = 0; i < 100000; i++) {
f.call(123456789, 0);
f.call(123456789, 2);
}
});
console.log(time.format(0) + 'ms');
}
// if not using async, browser will stop responding while running.
// this will create a new thread to benchmark
async = [];
function next() {
setTimeout(function () {
f = async.shift();
f && f();
next();
}, 10);
}
console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
Я нашел это от: accounting.js. Это очень легко и идеально подходит для моей потребности.
// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00
// European formatting (custom symbol and separators), can also use options object as second parameter:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99
// Negative values can be formatted nicely:
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
// Euro currency symbol to the right
accounting.formatMoney(5318008, {symbol: "€", precision: 2, thousand: ".", decimal : ",", format: "%v%s"}); // 1.008,00€
Простая опция для правильного размещения в запятой, обращая сначала строку и основное регулярное выражение.
String.prototype.reverse = function() {
return this.split('').reverse().join('');
};
Number.prototype.toCurrency = function( round_decimal /*boolean*/ ) {
// format decimal or round to nearest integer
var n = this.toFixed( round_decimal ? 0 : 2 );
// convert to a string, add commas every 3 digits from left to right
// by reversing string
return (n + '').reverse().replace( /(\d{3})(?=\d)/g, '$1,' ).reverse();
};
Пример Патрика Дежардинса (ex Daok) хорошо работал у меня. Я пошлю к coffeescript, если кто-то заинтересован.
Number.prototype.toMoney = (decimals = 2, decimal_separator = ".", thousands_separator = ",") ->
n = this
c = if isNaN(decimals) then 2 else Math.abs decimals
sign = if n < 0 then "-" else ""
i = parseInt(n = Math.abs(n).toFixed(c)) + ''
j = if (j = i.length) > 3 then j % 3 else 0
x = if j then i.substr(0, j) + thousands_separator else ''
y = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_separator)
z = if c then decimal_separator + Math.abs(n - i).toFixed(c).slice(2) else ''
sign + x + y + z