Я предполагаю, что вердикт: я не могу программно однозначно идентифицировать компьютер, который посещает мой веб-сайт.
У меня есть следующий вопрос. Когда я использую машину, которая никогда не посещала мой веб-сайт онлайн-банкинга, меня спрашивают о дополнительной аутентификации. то, если я вернусь во второй раз на сайт онлайн-банкинга, я не получаю дополнительную аутентификацию. прочитав ответы на мой вопрос, я решил, что это должен быть куки-файл. поэтому я удалил все куки в IE и перешел на мой сайт онлайн-банкинга, полностью ожидая, что вас снова зададут вопросы аутентификации. к моему удивлению, я не спросил. разве это не приводит к тому, что банк верит, что банк делает какую-то маркировку для ПК, которая не включает в себя куки?
далее, после многоголоса сегодня я нашел следующую компанию, которая утверждает, что продает решение, которое однозначно идентифицирует машины, которые посетите веб-сайт. http://www.the41.com/products.asp .
Я ценю всю полезную информацию, если вы могли бы уточнить эту противоречивую информацию, которую я нашел, я был бы очень благодарен ей.
Хорошо, основываясь на том, что вы сказали, я использую это:
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,
Если вы можете использовать современный синтаксис 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>
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;
}
Вот самый короткий и лучший способ конвертировать числа в формат валюты:
function toCurrency(amount){
return amount.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
// usage: toCurrency(3939920.3030);
Ура! Anunay
var number = 3500;
alert(new Intl.NumberFormat().format(number));
// → "3,500" if in US English locale
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat Пример: использование локалей
В этом примере показаны некоторые из вариации в локализованных числовых форматах. Чтобы получить формат языка, используемого в пользовательском интерфейсе вашего приложения, обязательно укажите этот язык (и, возможно, некоторые запасные языки), используя аргумент locales:
var number = 123456.789;
// Немецкий язык использует запятую в качестве десятичного разделителя и точку для тысяч console.log (new Intl.NumberFormat ('de-DE'). Format (number)); // → 123.456,789
// В большинстве говорящих на арабском языке арабских языков используются настоящие арабские цифры console.log (new Intl.NumberFormat ('ar-EG'). Format (number)); // → ١٢٣٤٥٦ ٫ ٧٨٩
// Индия использует разделители тысяч / лакх / крор console.log (новый Intl.NumberFormat ('en-IN'). Format (number));
Минималистический подход, который просто соответствует первоначальным требованиям:
function formatMoney(n) {
return "$ " + (Math.round(n * 100) / 100).toLocaleString();
}
@Daniel Magliola: Вы правы, вышесказанное было поспешной, неполной реализацией. Вот исправленная реализация:
function formatMoney(n) {
return "$ " + n.toLocaleString().split(".")[0] + "."
+ n.toFixed(2).split(".")[1];
}
В JavaScript нет эквивалента «formatNumber». Вы можете написать это самостоятельно или найти библиотеку, которая уже делает это.
Потому что, почему бы не добавить еще один ответ. Я основал это на ответ от 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
Просто для удовольствия.
Код от 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 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));
}
Без циклов, без регулярных выражений, без массивов, без экзотических условных выражений.
Мне нравится самый короткий ответ от VisionN, за исключением случаев, когда мне нужно изменить его для числа без десятичной точки (123 доллара вместо 123,00 долларов США), он не работает, поэтому вместо быстрого копирования / вставки мне нужно расшифровать тайный синтаксис JavaScript регулярное выражение. [1 131]
Вот оригинальное решение
n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '[110]amp;,');
Я сделаю это немного длиннее:
var re = /\d(?=(\d{3})+\.)/g;
var subst = '[111]amp;,';
n.toFixed(2).replace(re, subst);
Re
part here (поиск части в строке заменяет) означает
\d
) ?=
...) (взгляд вперед) (
... )+
\d{3}
) \.
) g
) Subst
здесь часть означает
[1114]amp;
), за которым следует запятая. Поскольку мы используем 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, '[113]amp;,');
Это выражение даст
1234567.89 -> 1,234,567
Также вместо конца строки ($
) в приведенном выше регулярном выражении вы также можете выбрать границу слова (\b
).
Заранее извиняюсь за неправильное толкование какой-либо части обработки регулярных выражений.
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
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
Более быстрый способ с помощью регулярных выражений?
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;
}
@tggagne это правильно. Мое решение ниже не является хорошим из-за округления поплавка. А функции toLocaleString не хватает некоторой поддержки браузера. Я оставлю комментарии ниже для архивных целей того, что НЕ нужно делать. :)
(старое решение) Вместо этого используйте раствор Патрика Дежардена.
Это краткое решение, использующее toLocaleString (), которое поддерживается с версии 1.0 Javascript. В этом примере валюта указана в долларах США, но ее можно перевести в фунты, используя вместо фунта «доллар».
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 для получения дополнительной информации.
Вот реализация 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) : '');
});
Уже есть хорошие ответы. Вот простая попытка для развлечения:
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)
)
Мне было трудно найти простую библиотеку для работы с датой и валютой, поэтому я создал свою: https://github.com/dericeira/slimFormatter.js
Простая как это:
var number = slimFormatter.currency(2000.54);
Этот ответ соответствует следующим критериям:
Этот код основан на понятиях из других ответов. Это скорость выполнения должна быть среди лучших опубликованных здесь, если это вызывает беспокойство.
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 + "\"");
}
}
Я хотел ванильное решение 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");
Вот простой форматировщик в vanilla 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;
}
Coffeescript для популярного ответа Патрика выше:
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 "")
javascript-number-formatter (ранее в Google Code )
#,##0.00
или с отрицанием -000.####
. # ##0,00
, #,###.##
, #'###.##
или любой тип не нумерованного символа. #,##,#0.000
или #,###0.##
все действительны. ##,###,##.#
или 0#,#00#.###0#
все в порядке. format( "0.0000", 3.141592)
. (отрывок из его README)
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;
}
Если количество является числом, скажем, -123
, то
amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
будет производить строку "-$123.00"
.
Вот полный рабочий пример .
Здесь уже есть несколько отличных ответов. Вот еще одна попытка, просто для удовольствия:
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"
Отредактировано: теперь оно будет обрабатывать и отрицательные числа
Вот мой ...
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;
}
у многих ответов были полезные идеи, но ни один из них не соответствовал моим потребностям. Поэтому я использовал все идеи и создал этот пример:
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 ([110]) {
return ([110].charAt(0)==".")
? ((add_nk=""),(kommaSgn + [110].substring(1)))
: ([110] + 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([110],$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([110],$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([110]){
if([110]!="")n_dig=[110];
});
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 , которое должно быть гибким, но очень простым использовать , и я определил его следующим образом; паттерны:
%[<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, строка формата - это строка, содержащая шаблоны, например. для евро : «% 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 заключает в себе регулярное выражение;
В-третьих, вызов типа «format (value, fmt)» неприемлем, потому что: хотя должна быть возможность форматировать разные коллекции объектов (например, ячеек столбца) с разными масками, я не хочу, чтобы что-то обрабатывалось форматирование строк в точке обработки. На данный момент я хочу только использовать форматирование, как в
для (var cell in cell) {do_something (cell.col.formatter (cell.value)); }
Какой формат - может быть, он определен в ini, в xml для каждого столбца или где-то еще ..., но анализирует и устанавливает форматы или имеет дело с интернационализацией ] обрабатывается в совершенно другом месте , и там я хочу назначить средство форматирования для коллекции, не думая о проблемах производительности:
col.formatter = Format_Numb (_getFormatForColumn (...)) ;
В-четвертых, я хотел «толерантное» решение , поэтому прохождение fe строка вместо числа должна возвращать просто строку, но «null» должна возвращать пустую строку.
(Также форматирование «% 4.2f» не должно обрезать что-либо, если значение слишком велико.)
И последнее, но не менее важное: оно должно быть читаемым и легко расширяемым , БЕЗ оказывает какое-либо влияние на производительность ... Например, если кому-то нужны "восьмеричные значения", пожалуйста, обратитесь к строкам со словами "... можно расширить ..." - я думаю, что это должно быть очень простой задачей.
Я сосредоточился на производительности. Каждая «процедура обработки» (например, _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; извините, я не могу сослаться на них всех, но спасибо всем экспертам.
Так почему никто не предложил следующее?
(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})
Работает для большинства / некоторых браузеров: