Как я могу отформатировать числа как строку валюты в JavaScript?
-
02-07-2019 - |
Вопрос
Я хотел бы отформатировать цену в JavaScript.
Мне бы нужна функция, которая принимает float
в качестве аргумента и возвращает string
отформатирован следующим образом:
"$ 2,500.00"
Каков наилучший способ сделать это?
Решение 12
Хорошо, основываясь на том, что вы сказали, я использую это:
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>
Используйте это вот так:
(123456789.12345).formatMoney(2, ".", ",");
Если вы всегда собираетесь использовать '.' и ',', вы можете исключить их из вызова вашего метода, и метод будет использовать их по умолчанию для вас.
(123456789.12345).formatMoney(2);
Если в вашей культуре эти два символа перевернуты (т. е.Европейцы) и вы хотели бы использовать значения по умолчанию, просто вставьте следующие две строки в formatMoney
способ:
d = d == undefined ? "," : d,
t = t == undefined ? "." : t,
Пользовательская функция (ES6)
Если вы можете использовать современный синтаксис ECMAScript (т. е.через Babel), вы можете использовать вместо этого эту более простую функцию:
function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
try {
decimalCount = Math.abs(decimalCount);
decimalCount = isNaN(decimalCount) ? 2 : decimalCount;
const negativeSign = amount < 0 ? "-" : "";
let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
let j = (i.length > 3) ? i.length % 3 : 0;
return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
} catch (e) {
console.log(e)
}
};
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
Идея, лежащая в основе этого решения, заключается в замене совпадающих разделов первым совпадением и запятой, т.е. '$&,'
.Сопоставление выполняется с помощью перспективный подход.Вы можете прочитать это выражение следующим образом "сопоставьте число, если за ним следует последовательность из трех наборов чисел (одного или более) и точки".
ТЕСТЫ:
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'
в примере) использовать системный языковой стандарт (пользовательский языковой стандарт в случае, если код выполняется в браузере).
Intl.NumberFormat против Number.prototype.toLocaleString
Последнее замечание , сравнивающее это со старым .toLocaleString
.Они оба предлагают практически одинаковую функциональность.Однако toLocaleString в своих более старых воплощениях (до Intl) на самом деле не поддерживает локали:он использует системный языковой стандарт.Поэтому убедитесь, что вы используете правильную версию (MDN предлагает проверить наличие Intl
).Кроме того, производительность обоих одинакова для одинокий элемент, но если у вас много чисел для форматирования, используя Intl.NumberFormat
это примерно в 70 раз быстрее.Вот как использовать toLocaleString
:
(2500).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
}); /* $2,500.00 */
Некоторые замечания по поддержке браузера
- В настоящее время поддержка браузеров больше не является проблемой: в США / ЕС поддержка составляет 97%.
- Что касается других частей мира (поддерживается 92%), то наибольшими нарушителями в плане поддержки являются UC Mobile (держись от этого подальше) и Opera Mini (искалеченный дизайн)
- Существует прокладка чтобы поддерживать его в старых браузерах
- Взгляните на Каниуз для получения дополнительной информации
Взгляните на JavaScript Число возразите и посмотрите, может ли это вам помочь.
toLocaleString()
отформатирует число, используя разделитель тысяч, зависящий от местоположения.toFixed()
округлит число до определенного количества знаков после запятой.
Чтобы использовать их одновременно, тип значения должен быть изменен обратно на число, потому что они оба выводят строку.
Пример:
Number(someNumber.toFixed(1)).toLocaleString()
Ниже приведен Патрик Дежарден (псевдоним Даок) код с добавлением небольшого количества комментариев и некоторыми незначительными изменениями:
/*
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 [https://stackoverflow.com/questions/411352/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"
.
Вот полный рабочий пример.
Вот лучший форматировщик 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) : "");
};
Он был переформатирован и позаимствован отсюда: https://stackoverflow.com/a/149099/751484
Вам придется указать свое собственное обозначение валюты (вы использовали $ выше).
Назовите это следующим образом (хотя обратите внимание, что аргументы по умолчанию равны 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);
Так почему же никто не предложил следующее?
(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})
Работает для большинства / некоторых браузеров:
Numeral.js - библиотека js для удобного форматирования чисел от @adamwdraper
numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
Я пользуюсь библиотекой Глобализировать (от Microsoft):
Это отличный проект по локализации чисел, валют и дат и их автоматическому правильному форматированию в соответствии с языком пользователя!... и несмотря на то, что это должно быть расширение jQuery, в настоящее время это на 100% независимая библиотека.Я предлагаю вам всем попробовать это!:)
javascript-форматер чисел (ранее в Код Google)
- Короткий, быстрый, гибкий, но в то же время автономный.
Всего 75 строк, включая информацию о лицензии MIT, пустые строки и комментарии. - Принимайте стандартное форматирование чисел, например
#,##0.00
или с отрицанием-000.####
. - Принимайте любой формат страны, например
# ##0,00
,#,###.##
,#'###.##
или любой тип не нумерующего символа. - Принимайте любые числа из группы цифр.
#,##,#0.000
или#,###0.##
все они действительны. - Принимайте любое избыточное / защищенное от ошибок форматирование.
##,###,##.#
или0#,#00#.###0#
все в порядке. - Автоматическое округление номера.
- Простой интерфейс, просто укажите маску и значение следующим образом:
format( "0.0000", 3.141592)
. - Включите префикс и суффикс вместе с маской
(выдержка из его README)
Существует порт PHP-функции "number_format" на JavaScript.
Я нахожу это очень полезным, так как оно простое в использовании и узнаваемое для разработчиков 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 Джонатану М. за предоставление оригинального метода.Поскольку это явно средство форматирования валюты, я пошел дальше и добавил символ валюты (по умолчанию '$') в выходные данные и добавил запятую по умолчанию в качестве разделителя тысяч.Если вам на самом деле не нужен символ валюты (или разделитель тысяч), просто используйте "" (пустую строку) в качестве аргумента для него.
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());
Патрик Дежарден'ответ выглядит неплохо, но я предпочитаю, чтобы мой 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
Исправленный в javascript
var num = new Number(349);
document.write("$" + num.toFixed(2));
Основная часть - это вставка тысячных разделителей, что можно было бы сделать следующим образом:
<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 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)
)
Вот версия с большим количеством опций в окончательном выводе, позволяющая форматировать разные валюты в разных локальных форматах.
// higher order function that takes options then a price and will return the formatted price
const makeMoneyFormatter = ({
sign = '$',
delimiter = ',',
decimal = '.',
append = false,
precision = 2,
round = true,
custom
} = {}) => value => {
const e = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]
value = round
? (Math.round(value * e[precision]) / e[precision])
: parseFloat(value)
const pieces = value
.toFixed(precision)
.replace('.', decimal)
.split('')
let ii = pieces.length - (precision ? precision + 1 : 0)
while ((ii-=3) > 0) {
pieces.splice(ii, 0, delimiter)
}
if (typeof custom === 'function') {
return custom({
sign,
float: value,
value: pieces.join('')
})
}
return append
? pieces.join('') + sign
: sign + pieces.join('')
}
// create currency converters with the correct formatting options
const formatDollar = makeMoneyFormatter()
const formatPound = makeMoneyFormatter({
sign: '£',
precision: 0
})
const formatEuro = makeMoneyFormatter({
sign: '€',
delimiter: '.',
decimal: ',',
append: true
})
const customFormat = makeMoneyFormatter({
round: false,
custom: ({ value, float, sign }) => `SALE:$${value}USD`
})
console.log(
formatPound(1000),
formatDollar(10000.0066),
formatEuro(100000.001),
customFormat(999999.555)
)
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;
}
От Повелитель воли.
Возможно, это немного запоздало, но вот метод, который я только что разработал для коллеги, чтобы добавить язык с учетом локали .toCurrencyString()
функция для всех номеров.Интернализация предназначена только для группировки чисел, А НЕ для знака валюты - если вы выводите доллары, используйте "$"
как поставлено, потому что $123 4567
в Японии или Китае - это такое же количество долларов, как $1,234,567
находится здесь, в США.Если вы выводите евро / etc., то измените знак валюты на "$"
.
Объявите это в любом месте своей ГОЛОВЫ или там, где это необходимо, непосредственно перед тем, как вам нужно будет это использовать:
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);
}
}
отредактировано 08.08.2010/30:добавлена опция для установки количества десятичных разрядов. отредактировано 23.08.2011:добавлена опция установки количества десятичных разрядов равным нулю.
Вот несколько решений, все они проходят набор тестов, включая набор тестов и бенчмарк, если вы хотите скопировать и вставить для тестирования, попробуйте В этом Суть.
Метод 0 (регулярное выражение)
Основываться на https://stackoverflow.com/a/14428340/1877620, но исправьте, если нет десятичной точки.
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('.');
}
}
Способ 1
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's 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('.');
};
}
Способ 2 (Разбить на массив)
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('.');
};
}
Способ 3 (Цикл)
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();
};
Пример Патрика Дежардена (экс-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