Я хотел бы отформатировать цену в 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(n, c, d, t) {
var c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
t = t == undefined ? "," : t,
s = n < 0 ? "-" : "",
i = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(c))),
j = (j = i.length) > 3 ? j % 3 : 0;
return s + (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) : "");
};
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
Европейцы), и вы хотите использовать значения по умолчанию, просто вставьте следующие две строки в методе formatMoney
:
d = d == undefined ? "," : d,
t = t == undefined ? "." : t,
Если вы можете использовать современный синтаксис 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>
(1.005).toFixed(2)
.
d
и t
на .
и ,
соответственно, чтобы вам не приходилось указывать их каждый раз. Кроме того, я рекомендую изменить начало оператора return
образом: return s + '$' + [rest]
, иначе вы не получите знак доллара.
(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/
.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")
.
Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Javascript имеет средство форматирования чисел (часть Интернационализации API).
// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
// the default value for minimumFractionDigits depends on the currency
// and is usually already 2
});
formatter.format(2500); /* $2,500.00 */
Используйте undefined
вместо первого аргумента (в данном примере 'en-US'
), чтобы использовать языковой стандарт системы (языковой стандарт пользователя в случае, если код выполняется в браузере).
Последнее замечание, сравнивающее это со старшим. toLocaleString
. Они оба предлагают по существу одинаковую функциональность. Однако toLocaleString в его более старых версиях (pre-Intl) фактически не поддерживает локали: он использует системную локаль. Поэтому, чтобы убедиться, что вы используете правильную версию, MDN предлагает проверить наличие Intl
. Так что, если вам все равно нужно проверить Intl, почему бы не использовать его вместо этого? Однако, если вы решите использовать toLocaleString
, он также исправляет toLocaleString
, поэтому в этом случае вы можете использовать его без каких-либо хлопот:
(2500).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
}); /* $2,500.00 */
Взгляните на объект JavaScript Number и посмотрите, может ли он вам помочь.
toLocaleString()
будет отформатировать число, используя разделитель тысяч тысяч адресов.toFixed()
будет округлять число до определенного числа десятичных знаков.Чтобы использовать их одновременно, значение должно иметь свой тип, измененный обратно на число, потому что они оба выводят строку.
Пример:
Number(someNumber.toFixed(1)).toLocaleString()
Ниже приведен код Patrick Desjardins (псевдоним 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
больше не может быть пустой строкой (decimal_sep
какой-то десятичный разделитель)
мы используем typeof thousands_sep === 'undefined'
как предложено в разделе Как лучше всего определить, не передается ли аргумент в функцию JavaScript
(+n || 0)
не нужен, потому что this
объект Number
parseInt
вызывается по абсолютному значению части числа INTEGER. Партия INTEGER не может начинаться с нуля, если только это не ноль! И parseInt(0) === 0
восьмеричный или десятичный.
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) : "");
};
Он был переформатирован и заимствован отсюда: https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-dollars-currency-string-in-javascript
Вам нужно будет указать свой собственный валютный указатель (вы использовали $выше).
Назовите его так (хотя обратите внимание, что аргументы по умолчанию равны 2, запятой и периоду, поэтому вам не нужно указывать какие-либо аргументы, если вы предпочитаете):
var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"
var
.
Здесь уже есть отличные ответы. Вот еще одна попытка, просто для удовольствия:
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"
Отредактировано: теперь он будет обрабатывать и отрицательные числа
i = orig.length - i - 1
в i = orig.length - i - 1
. Тем не менее, еще один обход массива.
Я думаю, что вы хотите 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"
Я использую библиотеку Globalize (от Microsoft):
Это отличный проект для локализации чисел, валют и дат и автоматического их форматирования в соответствии с пользовательским языком!... и, несмотря на это, должно быть расширение jQuery, в настоящее время это 100% независимая библиотека. Я предлагаю вам все попробовать!:)
javascript-number-formatter (ранее на Google Code)
#,##0.00
или с отрицанием -000.####
.# ##0,00
, #,###.##
, #'###.##
или любой символ без нумерации.#,##,#0.000
или #,###0.##
являются действительными.##,###,##.#
или 0#,#00#.###0#
все в порядке.format( "0.0000", 3.141592)
.(выдержка из его README)
+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());
Существует 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'
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));
toFixed()
toFixed()
является функцией объекта Number
и не будет работать с var num
если это String
, поэтому мне помог дополнительный контекст.
Не видел этого. Это довольно лаконично и легко понять.
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)
)
Я предлагаю класс NumberFormat из API визуализации Google.
Вы можете сделать что-то вроде этого:
var formatter = new google.visualization.NumberFormat({
prefix: '$',
pattern: '#,###,###.##'
});
formatter.formatValue(1000000); // $ 1,000,000
Надеюсь, это поможет.
Это может быть немного поздно, но вот метод, который я только что обработал для коллеги, чтобы добавить функцию .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"
Основная часть - вставка тысяч разделителей, что можно сделать следующим образом:
<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)));">
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.
Я нашел это от: 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€
$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );
- показать 1.000,00 E
Вот некоторые решения: все передают набор тестов, набор тестов и контрольный тест, если вы хотите скопировать и вставить для тестирования, попробуйте This Gist.
База на https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-dollars-currency-string-in-javascript, но исправить, если нет десятичной точки.
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();
Как обычно, существует несколько способов сделать одно и то же, но я бы избегал использования 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: добавлена возможность установить число десятичных цифр в ноль.
Простая опция для правильного размещения в запятой, обращая сначала строку и основное регулярное выражение.
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
Кодовая база YUI использует следующее форматирование:
format: function(nData, oConfig) {
oConfig = oConfig || {};
if(!YAHOO.lang.isNumber(nData)) {
nData *= 1;
}
if(YAHOO.lang.isNumber(nData)) {
var sOutput = nData + "";
var sDecimalSeparator = (oConfig.decimalSeparator) ? oConfig.decimalSeparator : ".";
var nDotIndex;
// Manage decimals
if(YAHOO.lang.isNumber(oConfig.decimalPlaces)) {
// Round to the correct decimal place
var nDecimalPlaces = oConfig.decimalPlaces;
var nDecimal = Math.pow(10, nDecimalPlaces);
sOutput = Math.round(nData*nDecimal)/nDecimal + "";
nDotIndex = sOutput.lastIndexOf(".");
if(nDecimalPlaces > 0) {
// Add the decimal separator
if(nDotIndex < 0) {
sOutput += sDecimalSeparator;
nDotIndex = sOutput.length-1;
}
// Replace the "."
else if(sDecimalSeparator !== "."){
sOutput = sOutput.replace(".",sDecimalSeparator);
}
// Add missing zeros
while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
sOutput += "0";
}
}
}
// Add the thousands separator
if(oConfig.thousandsSeparator) {
var sThousandsSeparator = oConfig.thousandsSeparator;
nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
var sNewOutput = sOutput.substring(nDotIndex);
var nCount = -1;
for (var i=nDotIndex; i>0; i--) {
nCount++;
if ((nCount%3 === 0) && (i !== nDotIndex)) {
sNewOutput = sThousandsSeparator + sNewOutput;
}
sNewOutput = sOutput.charAt(i-1) + sNewOutput;
}
sOutput = sNewOutput;
}
// Prepend prefix
sOutput = (oConfig.prefix) ? oConfig.prefix + sOutput : sOutput;
// Append suffix
sOutput = (oConfig.suffix) ? sOutput + oConfig.suffix : sOutput;
return sOutput;
}
// Still not a Number, just return unaltered
else {
return nData;
}
}
ему понадобится редактирование, поскольку библиотека YUI будет настраиваться, например, заменить oConfig.decimalSeparator на "."
55 ответов явно требуют другого.
function centsToDollaString(x){
var cents = x + ""
while(cents.length < 4){
cents = "0" + cents;
}
var dollars = cents.substr(0,cents.length - 2)
var decimal = cents.substr(cents.length - 2, 2)
while(dollars.length % 3 != 0){
dollars = "0" + dollars;
}
str = dollars.replace(/(\d{3})(?=\d)/g, "$1" + ",").replace(/^0*(?=.)/,"");
return "$" + str + "." + decimal;
}
@tggagne верен. Мое решение ниже не хорошо из-за округления поплавка. И функции toLocaleString не хватает поддержки браузера. Я оставлю ниже комментарии для архивных целей того, что НЕ делать.:)
(старое решение) Вместо этого используйте решение Патрика Дежардинса.
Это краткое решение, использующее toLocaleString(), которое поддерживается с версии Javascript версии 1.0. Этот пример обозначает валюту в долларах США, но ее можно переключить на фунты, используя "GBP" вместо "USD".
var formatMoney = function (value) {
// Convert the value to a floating point number in case it arrives as a string.
var numeric = parseFloat(value);
// Specify the local currency.
return numeric.toLocaleString('USD', { style: 'currency', currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
Подробнее см. https://marcoscaceres.github.io/jsi18n/#localize_currency.
Вы никогда не должны жестко кодировать свое решение, потому что это вызовет проблемы с обслуживанием, поскольку вы добавите больше локалей. И вы всегда должны использовать инструменты интернационализации для этой проблемы, потому что сложность форматирования чисел очень высока, так как вы добавляете все больше и больше локалей. Просто подумайте о том, как отформатировать ту же сумму, но вместо этого используйте арабские цифры? Или отформатировать ту же сумму на немецком языке? они используют разные символы для разделителя тысяч разделителей и фракций.
Что касается инструмента интернационализации, я использую l10ns (http://l10ns.org).
Вы просто пишете получатель для вашей локализованной строки.
var l = requireLocalizations('en-US');
var string = l('CURRENCY_AMOUNT', {
price: {
code: 'USD', //ISO currency code
amount: 2500
}
});
console.log(string) // Outputs '$ 2,500.00'
И определите свое сообщение возврата в своем инструменте интерфейса перевода.
{price, number, ¤ #,##0.00}
Третий приведенный выше аргумент называется десятичным паттерном. И он позволяет вам определить практически любой желаемый формат (мы используем decimal pattern
, потому что вам нужно пространство между символом и суммой). Но для валюты, пожалуйста, используйте определенный десятичный шаблон по умолчанию, определенный CLDR. CLDR - это хранилище данных, которое используют многие организации, такие как Google, IBM, Yahoo и т.д. Для получения данных локализации. И одна из данных локализации, которую мы можем получить, заключается в форматировании суммы валюты. Их по умолчанию decimal pattern
для английского языка ¤#,##0.00
. И мы можем использовать этот шаблон, просто введя следующий текст в интерфейс трансляции.
{price, currency, local, symbol}
Для получения дополнительной информации ознакомьтесь с документацией .
Функция обработки валютного выпуска, включая негативы.
Результат:
$ 5.23
- $5,23
function formatCurrency(total) {
var neg = false;
if(total < 0) {
neg = true;
total = Math.abs(total);
}
return (neg ? "-$" : '$') + parseFloat(total, 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString();
}
http://code.google.com/p/javascript-number-formatter/:
ОБНОВЛЕНИЕ Это мои домашние утилиты pp
для большинства распространенных задач:
var NumUtil = {};
/**
Petty print 'num' wth exactly 'signif' digits.
pp(123.45, 2) == "120"
pp(0.012343, 3) == "0.0123"
pp(1.2, 3) == "1.20"
*/
NumUtil.pp = function(num, signif) {
if (typeof(num) !== "number")
throw 'NumUtil.pp: num is not a number!';
if (isNaN(num))
throw 'NumUtil.pp: num is NaN!';
if (num < 1e-15 || num > 1e15)
return num;
var r = Math.log(num)/Math.LN10;
var dot = Math.floor(r) - (signif-1);
r = r - Math.floor(r) + (signif-1);
r = Math.round(Math.exp(r * Math.LN10)).toString();
if (dot >= 0) {
for (; dot > 0; dot -= 1)
r += "0";
return r;
} else if (-dot >= r.length) {
var p = "0.";
for (; -dot > r.length; dot += 1) {
p += "0";
}
return p+r;
} else {
return r.substring(0, r.length + dot) + "." + r.substring(r.length + dot);
}
}
/** Append leading zeros up to 2 digits. */
NumUtil.align2 = function(v) {
if (v < 10)
return "0"+v;
return ""+v;
}
/** Append leading zeros up to 3 digits. */
NumUtil.align3 = function(v) {
if (v < 10)
return "00"+v;
else if (v < 100)
return "0"+v;
return ""+v;
}
NumUtil.integer = {};
/** Round to integer and group by 3 digits. */
NumUtil.integer.pp = function(num) {
if (typeof(num) !== "number") {
console.log("%s", new Error().stack);
throw 'NumUtil.integer.pp: num is not a number!';
}
if (isNaN(num))
throw 'NumUtil.integer.pp: num is NaN!';
if (num > 1e15)
return num;
if (num < 0)
throw 'Negative num!';
num = Math.round(num);
var group = num % 1000;
var integ = Math.floor(num / 1000);
if (integ === 0) {
return group;
}
num = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + num;
num = NumUtil.align3(group) + " " + num;
}
return num;
}
NumUtil.currency = {};
/** Round to coins and group by 3 digits. */
NumUtil.currency.pp = function(amount) {
if (typeof(amount) !== "number")
throw 'NumUtil.currency.pp: amount is not a number!';
if (isNaN(amount))
throw 'NumUtil.currency.pp: amount is NaN!';
if (amount > 1e15)
return amount;
if (amount < 0)
throw 'Negative amount!';
if (amount < 1e-2)
return 0;
var v = Math.round(amount*100);
var integ = Math.floor(v / 100);
var frac = NumUtil.align2(v % 100);
var group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0) {
return group + "." + frac;
}
amount = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + amount + "." + frac;
amount = NumUtil.align3(group) + " " + amount;
}
return amount;
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat Пример: использование локалей
В этом примере показаны некоторые варианты форматов локализованных номеров. Чтобы получить формат языка, используемого в пользовательском интерфейсе вашего приложения, обязательно укажите этот язык (и, возможно, некоторые резервные языки), используя аргумент locales:
var number = 123456.789;
//Немецкий использует запятую как десятичный разделитель и период для тысяч console.log(новый Intl.NumberFormat('de-DE'). format (number));//→ 123.456,789
//Арабский язык в большинстве стран арабского языка использует реальные арабские цифры console.log(новый Intl.NumberFormat('ar-EG'). format (number));//→ 123456. 789
//В Индии используются тысячи /lakh/crore separators console.log(new Intl.NumberFormat( 'ен-IN') формат (номер));.
Вам следует использовать инструмент интернационализации для решения этой проблемы, потому что, если вам это не нужно, вам нужно жестко закодировать много специфического кода, а количество перестановок бесконечно. Я использую l10ns. С L10ns вы можете просто определить свою строку сообщения как сумму валюты:
{price, currency, local, symbol}
Скомпилируйте сообщение:
$ l10ns compile
И попросите его и используйте его:
var l = requireLocalizations('en-US');
var carPrice = l('PRIZES__CAR_PRICE', { price: {
code: 'USD',
amount: 349
}});
// use carPrice...
PS. Не забывайте, что английский использует скобки ($ #, ## 0.00) для отрицательных сумм.
var number = 3500;
alert(new Intl.NumberFormat().format(number));
// → "3,500" if in US English locale
Код от Jonathan M выглядит сложным для меня, поэтому я переписал его и получил около 30% на FF v30 и 60% на ускорение Chrome v35 (http://jsperf.com/number-formating2):
Number.prototype.formatNumber = function(decPlaces, thouSeparator, decSeparator) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator == undefined ? "." : decSeparator;
thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
var n = this.toFixed(decPlaces);
if (decPlaces) {
var i = n.substr(0, n.length - (decPlaces + 1));
var j = decSeparator + n.substr(-decPlaces);
} else {
i = n;
j = '';
}
function reverse(str) {
var sr = '';
for (var l = str.length - 1; l >= 0; l--) {
sr += str.charAt(l);
}
return sr;
}
if (parseInt(i)) {
i = reverse(reverse(i).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator));
}
return i+j;
};
Использование:
var sum = 123456789.5698;
var formatted = '$' + sum.formatNumber(2,',','.'); // "$123,456,789.57"
Вот короткая и лучшая конвертация чисел в формат валюты:
function toCurrency(amount){
return amount.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
// usage: toCurrency(3939920.3030);
Ура! Anunay
toCurrency('123456.7890')
возвращает 123,456.7,890
. ИМХО, не должно быть никаких запятых в десятичных разрядах. Кроме того, выглядит хорошо!
Этот ответ отвечает следующим критериям:
Этот код построен на концепциях из других ответов. Эта скорость выполнения должна быть среди лучших, размещенных здесь, если это вызывает беспокойство.
var decimalCharacter = Number("1.1").toLocaleString().substr(1,1);
var defaultCurrencyMarker = "$";
function formatCurrency(number, currencyMarker) {
if (typeof number != "number")
number = parseFloat(number, 10);
// if NaN is passed in or comes from the parseFloat, set it to 0.
if (isNaN(number))
number = 0;
var sign = number < 0 ? "-" : "";
number = Math.abs(number); // so our signage goes before the $ symbol.
var integral = Math.floor(number);
var formattedIntegral = integral.toLocaleString();
// IE returns "##.00" while others return "##"
formattedIntegral = formattedIntegral.split(decimalCharacter)[0];
var decimal = Math.round((number - integral) * 100);
return sign + (currencyMarker || defaultCurrencyMarker) +
formattedIntegral +
decimalCharacter +
decimal.toString() + (decimal < 10 ? "0" : "");
}
Эти тесты работают только на американской языковой машине. Это решение было принято для простоты и потому, что это может привести к дрянной записи (плохая авто-локализация), что позволяет избежать проблем с выпуском.
var tests = [
// [ input, expected result ]
[123123, "$123,123.00"], // no decimal
[123123.123, "$123,123.12"], // decimal rounded down
[123123.126, "$123,123.13"], // decimal rounded up
[123123.4, "$123,123.40"], // single decimal
["123123", "$123,123.00"], // repeat subset of the above using string input.
["123123.123", "$123,123.12"],
["123123.126", "$123,123.13"],
[-123, "-$123.00"] // negatives
];
for (var testIndex=0; testIndex < tests.length; testIndex++) {
var test = tests[testIndex];
var formatted = formatCurrency(test[0]);
if (formatted == test[1]) {
console.log("Test passed, \"" + test[0] + "\" resulted in \"" + formatted + "\"");
} else {
console.error("Test failed. Expected \"" + test[1] + "\", got \"" + formatted + "\"");
}
}
toLocaleString хорош, но не работает во всех браузерах. Обычно я использую currencyFormatter.js(https://osrec.github.io/currencyFormatter.js/). Он довольно легкий и содержит все определения валюты и локали прямо из коробки. Это также хорошо при форматировании необычно отформатированных валют, таких как INR (число групп в лаках и крорах и т.д.). Также нет зависимостей!
OSREC.CurrencyFormatter.format(2534234, { currency: 'INR' });
// Returns ₹ 25,34,234.00
OSREC.CurrencyFormatter.format(2534234, { currency: 'EUR' });
// Returns 2.534.234,00 €
OSREC.CurrencyFormatter.format(2534234, { currency: 'EUR', locale: 'fr' });
// Returns 2 534 234,00 €
Вот реализация mootools 1.2 из кода, предоставленного XMLilley...
Number.implement('format', function(decPlaces, thouSeparator, decSeparator){
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator === undefined ? '.' : decSeparator;
thouSeparator = thouSeparator === undefined ? ',' : thouSeparator;
var num = this,
sign = num < 0 ? '-' : '',
i = parseInt(num = Math.abs(+num || 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(num - i).toFixed(decPlaces).slice(2) : '');
});
В JavaScript нет эквивалента "formatNumber". Вы можете написать его самостоятельно или найти библиотеку, которая уже делает это.
Способ Quiker с регулярным выражением?
Number.prototype.toMonetaryString=function(){var n=this.toFixed(2),m;
// var=this.toFixed(2).replace(/\./,','); for comma separator
// with a space for thousands separator
while ((m=n.replace(/(\d)(\d\d\d)\b/g,'$1 $2'))!=n) n=m;
return m;
}
String.prototype.fromMonetaryToNumber=function(s){
return this.replace(/[^\d-]+/g,'')/100;
}
Это может сработать:
function format_currency(v, number_of_decimals, decimal_separator, currency_sign){
return (isNaN(v)? v : currency_sign + parseInt(v||0).toLocaleString() + decimal_separator + (v*1).toFixed(number_of_decimals).slice(-number_of_decimals));
}
Нет циклов, не существует регулярных выражений, нет массивов, нет экзотических условностей.
Минималистский подход, который отвечает только оригинальным требованиям:
function formatMoney(n) {
return "$ " + (Math.round(n * 100) / 100).toLocaleString();
}
@Даниэль Маглиола: Вы правы, вышеупомянутое было поспешным, неполным воплощением. Здесь исправленная реализация:
function formatMoney(n) {
return "$ " + n.toLocaleString().split(".")[0] + "."
+ n.toFixed(2).split(".")[1];
}
Я хотел, чтобы ванильное javascript-решение автоматически возвращало десятичную часть.
function formatDollar(amount) {
var dollar = Number(amount).toLocaleString("us", "currency");
//decimals
var arrAmount = dollar.split(".");
if (arrAmount.length==2) {
var decimal = arrAmount[1];
if (decimal.length==1) {
arrAmount[1] += "0";
}
}
if (arrAmount.length==1) {
arrAmount.push("00");
}
return "$" + arrAmount.join(".");
}
console.log(formatDollar("1812.2");
Мне было трудно найти простую библиотеку для работы с датой и валютой, поэтому я создал мою: https://github.com/dericeira/slimFormatter.js
Простое:
var number = slimFormatter.currency(2000.54);
у многих ответов были полезные идеи, но ни один из них не соответствовал моим потребностям. Поэтому я использовал все идеи и построил этот пример:
function Format_Numb( fmt){
var decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
if(typeof decSgn==="undefined") decSgn = ".";
if(typeof kommaSgn==="undefined") kommaSgn= ",";
var s3digits=/(\d{1,3}(?=(\d{3})+(?=[.]|$))|(?:[.]\d*))/g;
var dflt_nk="00000000".substring(0,decimals);
//--------------------------------
// handler for pattern: "%m"
var _f_money= function( v_in){
var v=v_in.toFixed(decimals);
var add_nk=",00";
var arr= v.split(".");
return arr[0].toString().replace(s3digits, function ($0) {
return ($0.charAt(0)==".")
? ((add_nk=""),(kommaSgn + $0.substring(1)))
: ($0 + decSgn);
})
+ ( (decimals > 0)
? ( kommaSgn
+ (
(arr.length > 1)
? arr[1]
: dflt_nk
)
)
: ""
);
}
// handler for pattern: "%<len>[.<prec>]f"
var _f_flt= function( v_in,l,prec){
var v=(typeof prec !== "undefined") ? v_in.toFixed(prec):v_in;
return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
?(Array(l+1).join(" ") + v)
:v;
}
// handler for pattern: "%<len>x"
var _f_hex= function( v_in,l,flUpper){
var v= Math.round(v_in).toString(16);
if(flUpper) v=v.toUpperCase();
return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
?(Array(l+1).join("0") + v)
:v;
}
//...can be extended..., just add the function, f.e.: var _f_octal= function( v_in,...){
//--------------------------------
if( typeof(fmt)!=="undefined"){
//...can be extended..., just add the char,f.e."O": MFX -> MFXO
var rpatt=/(?:%([^%"MFX]*)([MFX]))|(?:"([^"]*)")|("|%%)/gi;
var _qu= "\"";
var _mask_qu= "\\\"";
var str= fmt.toString().replace( rpatt,function($0,$1,$2,$3,$4){
var f;
if(typeof $1 !== "undefined"){
switch($2.toUpperCase()){
case "M": f= "_f_money(v)"; break;
case "F": var n_dig0,n_dig1;
var re_flt=/^(?:(\d))*(?:[.](\d))*$/;
$1.replace(re_flt,function($0,$1,$2){
n_dig0=$1;
n_dig1=$2;
});
f= "_f_flt(v," + n_dig0 + "," + n_dig1 + ")"; break;
case "X": var n_dig="undefined";
var re_flt=/^(\d*)$/;
$1.replace(re_flt,function($0){
if($0!="")n_dig=$0;
});
f= "_f_hex(v," + n_dig + "," + ($2=="X") + ")"; break;
//...can be extended..., f.e.: case "O":
}
return "\"+"+f+"+\"";
} else if(typeof $3 !== "undefined"){
return _mask_qu + $3 + _mask_qu;
} else {
return ($4==_qu)?_mask_qu:$4.charAt(0);
}
});
var cmd= "return function(v){"
+ "if(typeof v === \"undefined\")return \"\";" //null returned as empty string
+ "if(!v.toFixed)return v.toString();" //not numb returned as string
+ "return \"" + str + "\";"
+ "}";
//...can be extended..., just add the function name in the 2 places:
return new Function( "_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex);
}
}
Во-первых, мне понадобилось C-style format-string-definition, которое должно быть гибким, но очень простым в использовании, и я определил его следующим образом; шаблоны:
%[<len>][.<prec>]f float, example "%f", "%8.2d", "%.3f"
%m money
%[<len>]x hexadecimal lower case, example "%x", "%8x"
%[<len>]X hexadecimal upper case, example "%X", "%8X"
потому что нет необходимости форматировать другие, а затем для меня для евро, я реализовал только "% m". Но это легко расширить... Как и в C, строка формата представляет собой строку, содержащую шаблоны, F.E. для евро: "% m €" (возвращает строки типа "8.129,33 €" )
Помимо гибкости мне понадобилось очень быстрое решение для обработки таблиц. Это означает, что при обработке тысяч ячеек обработка строки формата не должна выполняться более одного раза. Вызов типа "format (value, fmt)" не подходит для меня, но это должно быть разделено на два этапа:
// var formatter = Format_Numb( "%m €");
//simple example for Euro...
// but we use a complex example:
var formatter = Format_Numb("a%%%3mxx \"zz\"%8.2f°\" >0x%8X<");
// formatter is now a function, which can be used more than once (this is an example, that can be tested:)
var v1= formatter( 1897654.8198344);
var v2= formatter( 4.2);
... (and thousands of rows)
Кроме того, для производительности, _f_money закрывает regexp;
В-третьих, вызов типа "format (value, fmt)" неприемлем, потому что: Хотя должно быть возможно отформатировать различные коллекции объектов (например, ячейки столбца) с разными масками, я не хочу иметь что-то, чтобы обрабатывать строки форматирования в точке обработки. На данный момент я хочу использовать только USE форматирование, например,
для (ячейка var в ячейках) {do_something (cell.col.formatter( cell.value)); }
Какой формат - возможно, он определен в ini, в xml для каждого столбца или где-то еще..., но анализ и настройка форматов или работа с internationalizaton обрабатывается полностью другим место, и там я хочу назначить форматтер коллекции, не думая о проблемах с производительностью:
col.formatter = Format_Numb (_getFormatForColumn (...));
В-четвертых, мне понадобилось "толерантное" решение, поэтому прохождение f.e. строка вместо числа должна возвращать просто строку, но "null" должна возвращать пустую строку.
(Также форматирование "% 4.2f" не должно вырезать что-то, если значение слишком велико.)
И последнее, но не менее важное - оно должно быть легко читаемым и легко расширяемым, без каких-либо эффектов в производительности... Например, если кому-то нужны "восьмеричные значения", обратитесь к строкам с "... может быть расширен..." - я думаю, что это должна быть очень простая задача.
Мое основное внимание было сосредоточено на производительности. Каждая "процедура обработки" (fe_f_money) может быть инкапсулирована оптимизирована или обменена другими идеями в этом или другом потоке без изменения "подпрограмм подготовки" (анализ строк формата и создание функций), которые должны обрабатываться только один раз и в этом смысл не так критичен по производительности, как призывы к конверсии тысяч чисел.
Для всех, кто предпочитает методы чисел:
Number.prototype.format_euro=( function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%m €"));
var v_euro= (8192.3282).format_euro(); //results: 8.192,33 €
Number.prototype.format_hex= (function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%4x"));
var v_hex= (4.3282).format_hex();
Хотя я тестировал что-то, в коде может быть много ошибок. Так что это не готовый модуль, а просто идея и отправная точка для не-js-экспертов, подобных мне. Код содержит много и мало измененных идей из множества сообщений stackoverflow; извините, я не могу сослаться на все из них, но спасибо всем экспертам.
Мне нравится кратчайший ответ VisionN, за исключением случаев, когда мне нужно изменить его на число без десятичной точки ($ 123 вместо $123.00), это не сработает, поэтому вместо быстрой копии/вставки мне нужно расшифровать тайный синтаксис JavaScript регулярное выражение.
Вот оригинальное решение
n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
Я сделаю это немного дольше:
var re = /\d(?=(\d{3})+\.)/g;
var subst = '$&,';
n.toFixed(2).replace(re, subst);
Re
часть здесь (часть поиска в замене строки) означает
\d
)?=
...) (lookahead)(
... )+
\d{3}
)\.
)g
) Subst
здесь означает
$&
), за которым следует запятая.Поскольку мы используем string.replace
, все остальные тексты в строке остаются теми же, и только найденные цифры (те, за которыми следуют 3,6,9 и т.д. другие цифры) получают дополнительную запятую.
Итак, в количестве 1234567.89 цифры 1 и 4 соответствуют условию ( 1 23 4 567.89) и заменены на " 1," и " 4,", что приводит к 1 234 567,89.
Если нам вообще не нужна десятичная точка в долларовой сумме (т.е. $123 вместо $123.00), мы можем изменить регулярное выражение следующим образом:
var re2 = /\d(?=(\d{3})+$)/g;
Он полагается на конец строки ($
) вместо точки (\.
), и окончательное выражение будет (обратите внимание также на toFixed(0)
):
n.toFixed(0).replace(/\d(?=(\d{3})+$)/g, '$&,');
Это выражение даст
1234567.89 -> 1,234,567
Также вместо конца строки ($
) в регулярном выражении вы также можете выбрать границу слова (\b
).
Мои извинения заранее, если я неверно истолковал любую часть обработки регулярных выражений.
Потому что почему бы не добавить еще один ответ. Я основывал это на ответе VisioN.
function format (val) {
val = (+val).toLocaleString();
val = (+val).toFixed(2);
val += "";
return val.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1" + format.thousands);
}
(function (isUS) {
format.decimal = isUS ? "." : ",";
format.thousands = isUS ? "," : ".";
}(("" + (+(0.00).toLocaleString()).toFixed(2)).indexOf(".") > 0));
Я тестировал с входами:
[ ""
, "1"
, "12"
, "123"
, "1234"
, "12345"
, "123456"
, "1234567"
, "12345678"
, "123456789"
, "1234567890"
, ".12"
, "1.12"
, "12.12"
, "123.12"
, "1234.12"
, "12345.12"
, "123456.12"
, "1234567.12"
, "12345678.12"
, "123456789.12"
, "1234567890.12"
, "1234567890.123"
, "1234567890.125"
].forEach(function (item) {
console.log(format(item));
});
И получили следующие результаты:
0.00
1.00
12.00
123.00
1,234.00
12,345.00
123,456.00
1,234,567.00
12,345,678.00
123,456,789.00
1,234,567,890.00
0.12
1.12
12.12
123.12
1,234.12
12,345.12
123,456.12
1,234,567.12
12,345,678.12
123,456,789.12
1,234,567,890.12
1,234,567,890.12
1,234,567,890.13
Просто для удовольствия.
Coffeescript для Patrick популярный ответ выше:
Number::formatMoney = (decimalPlaces, decimalChar, thousandsChar) ->
n = this
c = decimalPlaces
d = decimalChar
t = thousandsChar
c = (if isNaN(c = Math.abs(c)) then 2 else c)
d = (if d is undefined then "." else d)
t = (if t is undefined then "," else t)
s = (if n < 0 then "-" else "")
i = parseInt(n = Math.abs(+n or 0).toFixed(c)) + ""
j = (if (j = i.length) > 3 then j % 3 else 0)
s + (if j then i.substr(0, j) + t else "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (if c then d + Math.abs(n - i).toFixed(c).slice(2) else "")
String.prototype.toPrice = function () {
var v;
if (/^\d+(,\d+)$/.test(this))
v = this.replace(/,/, '.');
else if (/^\d+((,\d{3})*(\.\d+)?)?$/.test(this))
v = this.replace(/,/g, "");
else if (/^\d+((.\d{3})*(,\d+)?)?$/.test(this))
v = this.replace(/\./g, "").replace(/,/, ".");
var x = parseFloat(v).toFixed(2).toString().split("."),
x1 = x[0],
x2 = ((x.length == 2) ? "." + x[1] : ".00"),
exp = /^([0-9]+)(\d{3})/;
while (exp.test(x1))
x1 = x1.replace(exp, "$1" + "," + "$2");
return x1 + x2;
}
alert("123123".toPrice()); //123,123.00
alert("123123,316".toPrice()); //123,123.32
alert("12,312,313.33213".toPrice()); //12,312,313.33
alert("123.312.321,32132".toPrice()); //123,312,321.32
Здесь простой форматирующий элемент в ваниле JS:
function numberFormatter (num) {
console.log(num)
var wholeAndDecimal = String(num.toFixed(2)).split(".");
console.log(wholeAndDecimal)
var reversedWholeNumber = Array.from(wholeAndDecimal[0]).reverse();
var formattedOutput = [];
reversedWholeNumber.forEach( (digit, index) => {
formattedOutput.push(digit);
if ((index + 1) % 3 === 0 && index < reversedWholeNumber.length - 1) {
formattedOutput.push(",");
}
})
formattedOutput = formattedOutput.reverse().join('') + "." + wholeAndDecimal[1];
return formattedOutput;
}
Я хочу внести свой вклад:
function toMoney(amount) {
neg = amount.charAt(0);
amount= amount.replace(/\D/g, '');
amount= amount.replace(/\./g , '');
amount= amount.replace(/\-/g, '');
var numAmount = new Number(amount);
amount= numAmount .toFixed(0).replace(/./g, function(c, i, a) {
return i > 0 && c !== "," && (a.length - i) % 3 === 0 ? "." + c : c;
});
if(neg == '-')
return neg+amount;
else
return amount;
}
Это позволяет вам преобразовывать числа в текстовое поле, где вы только можете помещать числа (рассмотрите этот сценарий)
Это очистит текстовое поле, где только подставлять цифры, даже если вы вставляете строку с цифрами и буквами или любым символом
<html>
<head>
<script language=="Javascript">
function isNumber(evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
if (key.length == 0) return;
var regex = /^[0-9\-\b]+$/;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
}
}
function toMoney(amount) {
neg = amount.charAt(0);
amount= amount.replace(/\D/g, '');
amount= amount.replace(/\./g , '');
amount= amount.replace(/\-/g, '');
var numAmount = new Number(amount);
amount= numAmount .toFixed(0).replace(/./g, function(c, i, a) {
return i > 0 && c !== "," && (a.length - i) % 3 === 0 ? "." + c : c;
});
if(neg == '-')
return neg+amount;
else
return amount;
}
function clearText(inTxt, newTxt, outTxt) {
inTxt = inTxt.trim();
newTxt = newTxt.trim();
if(inTxt == '' || inTxt == newTxt)
return outTxt;
return inTxt;
}
function fillText(inTxt, outTxt) {
inTxt = inTxt.trim();
if(inTxt != '')
outTxt = inTxt;
return outTxt;
}
</script>
</head>
<body>
$ <input name=reca2 id=reca2 type=text value="0" onFocus="this.value = clearText(this.value, '0', '');" onblur="this.value = fillText(this.value, '0'); this.value = toMoney(this.value);" onKeyPress="isNumber(event);" style="width:80px;" />
</body>
</html>
Уже есть хорошие ответы. Здесь простая попытка для удовольствия:
function currencyFormat(no) {
var ar = (+no).toFixed(2).split('.');
return [
numberFormat(ar[0]|0),
'.',
ar[1]
].join('');
}
function numberFormat(no) {
var str = no + '';
var ar = [];
var i = str.length -1;
while( i >= 0 ) {
ar.push( (str[i-2]||'') + (str[i-1]|| '')+ (str[i]|| ''));
i= i-3;
}
return ar.reverse().join(',');
}
Запустите несколько примеров
console.log(
currencyFormat(1),
currencyFormat(1200),
currencyFormat(123),
currencyFormat(9870000),
currencyFormat(12345),
currencyFormat(123456.232)
)
Мне нравится просто:
function formatPriceUSD(price) {
var strPrice = price.toFixed(2).toString();
var a = strPrice.split('');
if (price > 1000000000)
a.splice(a.length - 12, 0, ',');
if (price > 1000000)
a.splice(a.length - 9, 0, ',');
if (price > 1000)
a.splice(a.length - 6, 0, ',');
return '$' + a.join("");
}
function getMoney(A){
var a = new Number(A);
var b = a.toFixed(2); //get 12345678.90
a = parseInt(a); // get 12345678
b = (b-a).toPrecision(2); //get 0.90
b = parseFloat(b).toFixed(2); //in case we get 0.0, we pad it out to 0.00
a = a.toLocaleString();//put in commas - IE also puts in .00, so we'll get 12,345,678.00
//if IE (our number ends in .00)
if(a < 1 && a.lastIndexOf('.00') == (a.length - 3))
{
a=a.substr(0, a.length-3); //delete the .00
}
return a+b.substr(1);//remove the 0 from b, then return a + b = 12,345,678.90
}
alert(getMoney(12345678.9));
Это работает в FF и IE
Number(value)
.toFixed(2)
.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
Поскольку каждая проблема имеет однострочное решение:
Number.prototype.formatCurrency = function() { return this.toFixed(2).toString().split(/[-.]/).reverse().reduceRight(function (t, c, i) { return (i == 2) ? '-' + t : (i == 1) ? t + c.replace(/(\d)(?=(\d{3})+$)/g, '$1,') : t + '.' + c; }, '$'); }
Это достаточно легко изменить для разных локалей, просто измените "$ 1" на "$ 1". а также '.' к ',', чтобы поменять местами, и. в цифрах, а символ валюты можно изменить, изменив "$" в конце.
Или, если у вас есть ES6, вы можете просто объявить функцию со значениями по умолчанию:
Number.prototype.formatCurrency = function(thou = ',', dec = '.', sym = '$') { return this.toFixed(2).toString().split(/[-.]/).reverse().reduceRight(function (t, c, i) { return (i == 2) ? '-' + t : (i == 1) ? t + c.replace(/(\d)(?=(\d{3})+$)/g, '$1' + thou) : t + dec + c; }, sym); }
console.log((4215.57).formatCurrency())
$4,215.57
console.log((4216635.57).formatCurrency('.', ','))
$4.216.635,57
console.log((4216635.57).formatCurrency('.', ',', "\u20AC"))
€4.216.635,57
О, и он работает и для отрицательных чисел:
console.log((-6635.574).formatCurrency('.', ',', "\u20AC"))
-€6.635,57
console.log((-1066.507).formatCurrency())
-$1,066.51
И, конечно, вам не нужно иметь символ валюты
console.log((1234.586).formatCurrency(',','.',''))
1,234.59
console.log((-7890123.456).formatCurrency(',','.',''))
-7,890,123.46
console.log((1237890.456).formatCurrency('.',',',''))
1.237.890,46
Здесь моя...
function thousandCommas(num) {
num = num.toString().split('.');
var ints = num[0].split('').reverse();
for (var out=[],len=ints.length,i=0; i < len; i++) {
if (i > 0 && (i % 3) === 0) out.push(',');
out.push(ints[i]);
}
out = out.reverse() && out.join('');
if (num.length === 2) out += '.' + num[1];
return out;
}
Вот быстрый способ с помощью regexp и замены.
function formatCurrency( number, dp, ts ) {
var num = parseFloat( number ); //convert to float
var pw; //for IE
dp = parseInt( dp, 10 ); //decimal point
dp = isNaN( dp ) ? 2 : dp; //default 2 decimal point
ts = ts || ','; //thousands separator
return num != number ?
false : //return false for NaN
( ( 0.9 ).toFixed( 0 ) == '1' ? //for cater IE toFixed bug
num.toFixed( dp ) : //format to fix n decimal point with round up
( Math.round( num * ( pw = Math.pow( 10, dp ) || 1 ) ) / pw ).toFixed( dp ) //for fix ie toFixed bug on round up value like 0.9 in toFixed
).replace( /^(-?\d{1,3})((\d{3})*)(\.\d+)?$/, function( all, first, subsequence, dmp, dec ) { //separate string into different parts
return ( first || '' ) + subsequence.replace( /(\d{3})/g, ts + '$1' ) + ( dec || '' ); //add thousands seperator and re-join all parts
} );
}
formatNumber