Я хочу отформатировать цену в JavaScript. Мне нужна функция, которая принимает float
в качестве аргумента и возвращает string
в таком формате:
"$ 2,500.00"
Как лучше всего это сделать?
Я хочу отформатировать цену в JavaScript. Мне нужна функция, которая принимает float
в качестве аргумента и возвращает string
в таком формате:
"$ 2,500.00"
Как лучше всего это сделать?
В JavaScript есть средство форматирования чисел (часть API интернационализации).
// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
// These options are needed to round to whole numbers if that's what you want.
//minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
//maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
});
formatter.format(2500); /* $2,500.00 */
Используйте undefined
вместо первого аргумента ('en-US'
в примере), чтобы использовать языковой стандарт системы (языковой стандарт пользователя в случае, если код выполняется в браузере). Дальнейшее объяснение кода языкового стандарта.
Вот список кодов валют.
Последнее примечание, сравнивающее его со старым .toLocaleString
. Оба они предлагают практически одинаковые функции. Однако toLocaleString в своих более старых воплощениях (до Intl) не фактически поддерживает локали: он использует системный языковой стандарт. Поэтому при отладке старых браузеров убедитесь, что вы используете правильную версию ( MDN предлагает проверить наличие Intl
). Нет необходимости беспокоиться об этом, если вам не нужны старые браузеры или вы просто используете прокладка.
Кроме того, производительность обоих одинакова для одиночного элемента, но если вам нужно отформатировать много чисел, использование Intl.NumberFormat
будет примерно в 70 раз быстрее. Поэтому обычно лучше использовать Intl.NumberFormat
и создавать экземпляр только один раз при загрузке страницы. В любом случае, вот эквивалентное использование toLocaleString
:
(2500).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
}); /* $2,500.00 */
en-US
из коробки. Одно из решений - установить full-icu, см. здесь для получения дополнительной информации.parseFloat('$2,345.67'.replace(/[^0-9.]/g, ''))
. Разумеется, остерегайтесь плавающих валютных курсов.
- person aross; 26.08.2020
maximumFractionDigits: 0
, если хотите получить ответ в форме $2,500
. Так было бы: return (num).toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
- person Aljosha Novakovic; 25.03.2021
Это решение совместимо со всеми основными браузерами:
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>
(1.005).toFixed(2)
.
- person Ryan; 19.10.2010
d
и t
на .
и ,
соответственно, чтобы вам не приходилось указывать их каждый раз. Кроме того, я рекомендую изменить начало оператора return
следующим образом: return s + '$' + [rest]
, иначе вы не получите знак доллара.
- person Jason; 01.02.2011
d == undefined
используется, а typeof(d) === 'undefined'
должен быть на месте.
- person trejder; 27.08.2013
undefined
определяется JS, а не какими-то глупыми программистами, и вам следует использовать круглые скобки для typeof
, потому что без нее вы будете сравнивать ее с этой переменной с именем undefined
. Я не излагаю здесь свои мысли, я просто скопировал то, что выражено во многих ответах SO и во многих источниках. Сейчас нет времени искать пример, но вы обязательно его найдете, если погуглите еще немного.
- person trejder; 25.09.2013
undefined
оценивается как (void 0)
, пока глупый программист не вводит теневую undefined
локальную переменную и не выполняет повторную привязку window.undefined
. (Я считаю этот код нарушителем, а не код с использованием undefined
.)
- person user2864740; 18.11.2013
typeof d === 'undefined'
вместо d === undefined
, заключается в том, что при первом подходе вам не нужно заботиться о глупых разработчиках. Поскольку мир переполнен глупыми разработчиками, нам нужно тратить время на кодирование, а не на то, чтобы предвидеть возможные попытки глупых разработчиков испортить наш код, верно? :]
- person trejder; 18.11.2013
undefined
было переопределено на значение, отличное от (void 0)
, является средой, которую я не поддерживать. (В Python 2.x True и False были просто переменными - например, True,False=False,True
допустимо - но никогда не было никакого толчка, чтобы найти безопасный метод.)
- person user2864740; 18.11.2013
typeof(d) === 'undefined'
попытка предвидеть возможные попытки глупых разработчиков разрушить наш код? Если бы кто-то действительно переопределил undefined
, я бы не стал доверять им, чтобы они не сделали что-то еще, чтобы сломать ваш код.
- person Bob; 17.01.2014
toLocaleString()
делает то же самое с меньшим количеством кода. и более надежен. Ответили здесь
- person Mark Carpenter Jr; 27.06.2017
prototype
встроенного с помощью свойства enumerable, и ваш код даже не имеет смысла, даже если он действительно работает.
- person Patrick Roberts; 18.07.2017
formatMoney(someDate, 2)
вместо someDate.formatMoney(2)
, иначе вы получите Uncaught TypeError: Cannot read property 'value' of null, when it is.
- person Robin Wilson; 15.12.2018
j = (j = i.length) > 3 ? j % 3 : 0;
вызывает j до того, как она будет определена
- person Caio Mar; 31.05.2019
let j = 0;
перед использованием j. Проблемы с кодом у некоторых разработчиков браузеров ... Но в других случаях все еще работает. Странный.
- person JotaPardo; 26.04.2021
(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // 12,345.67
Идея этого решения заключается в замене совпавших разделов первым совпадением и запятой, то есть '$&,'
. Сопоставление выполняется с использованием подхода опережающего просмотра . Вы можете прочитать выражение как "соответствует числу, если за ним следует последовательность из трех наборов чисел (один или несколько) и точка".
ИСПЫТАНИЯ:
1 --> "1.00"
12 --> "12.00"
123 --> "123.00"
1234 --> "1,234.00"
12345 --> "12,345.00"
123456 --> "123,456.00"
1234567 --> "1,234,567.00"
12345.67 --> "12,345.67"
ДЕМО: http://jsfiddle.net/hAfMM/9571/
Вы также можете расширить прототип объекта Number
, добавив дополнительная поддержка любого количества знаков после запятой [0 .. n]
и размера числовых групп [0 .. x]
:
/**
* Number.prototype.format(n, x)
*
* @param integer n: length of decimal
* @param integer x: length of sections
*/
Number.prototype.format = function(n, x) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};
1234..format(); // "1,234"
12345..format(2); // "12,345.00"
123456.7.format(3, 2); // "12,34,56.700"
123456.789.format(2, 4); // "12,3456.79"
ДЕМО / ТЕСТЫ: http://jsfiddle.net/hAfMM/435/
В этой суперрасширенной версии вы может устанавливать разные типы разделителей:
/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed s: sections delimiter
* @param mixed c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
num = this.toFixed(Math.max(0, ~~n));
return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};
12345678.9.format(2, 3, '.', ','); // "12.345.678,90"
123456.789.format(4, 4, ' ', ':'); // "12 3456:7890"
12345678.9.format(0, 3, '-'); // "12-345-679"
ДЕМО / ТЕСТЫ: http://jsfiddle.net/hAfMM/612/
.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")
.
- person kalisjoshua; 21.03.2013
Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
- person Eric Anderson; 18.06.2013
this.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "$1,")
?
- person Abbas; 14.08.2013
\.
на $
(конец строки), то есть this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,")
.
- person VisioN; 15.08.2013
$1,
. Сопоставление выполняется с использованием подхода опережающего просмотра. Вы можете читать выражение как соответствует числу, если за ним следует последовательность из трех наборов чисел (один или несколько) и точка.
- person VisioN; 22.10.2013
$&
подход вам не подошел?
- person VisioN; 16.06.2015
Math.floor(n)
. Если вы хотите сделать его совместимым с JSHint, замените этот бит соответствующим образом.
- person VisioN; 18.06.2016
12514652.format()
рубином ... так?
- person Matrix; 22.09.2016
Number.prototype.toFixed
, который может неявно преобразовывать числа в экспоненциальной нотации в их полноразмерное строковое представление. См. Решение здесь: jsfiddle.net/hAfMM/4027.
- person VisioN; 20.10.2016
export const formatNumberToUSFormat = (numberToFormat: number | string) => { const stringNumber = numberToFormat.toString() return stringNumber.match(/\./g) ? stringNumber.replace(/\d(?=(\d{3})+\.)/g, '$&,') : stringNumber.replace(/\d(?=(\d{3})+$)/g, '$&,') }
- person Avernikoz; 12.10.2018
(012345).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
Он возвращает 5 349,00 вместо 12 345,00
- person olaoluwa_98; 12.05.2020
012345
5349
в десятичной системе счисления. Вам не разрешено использовать восьмеричные литералы в строгом режиме.
- person VisioN; 12.05.2020
(7642818.78).toFixed(2).replace(".",",").replace(/\d(?=(\d{3})+\,)/g, '$&.')
- person Paulo Bueno; 30.09.2020
Взгляните на объект JavaScript Number и посмотрим, может ли это вам помочь.
toLocaleString()
будет форматировать число, используя разделитель тысяч для конкретного местоположения.toFixed()
округляет число до определенного количества десятичных знаков.Чтобы использовать их одновременно, необходимо изменить тип значения на число, потому что оба они выводят строку.
Пример:
Number((someNumber).toFixed(1)).toLocaleString()
toLocaleString
, использующая системный языковой стандарт, и новая (несовместимая) версия, исходящая от ECMAScript Intl API. Объясняется здесь. Этот ответ, похоже, предназначен для старой версии.
- person aross; 14.09.2017
10000
превратится в "10,000"
, а не "10,000.00"
, что является желаемым поведением для форматирования валюты.
- person Burak; 07.06.2018
Ниже представлен Патрик Дежардинс (псевдоним Даок) код с небольшими комментариями и небольшими изменениями:
/*
decimal_sep: character used as decimal separator, 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 the user does not want to show any decimal
d = decimal_sep || '.', // If no decimal separator is passed, we use the dot as default decimal separator (we MUST use a decimal separator)
/*
According to [https://stackoverflow.com/questions/411352/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
the fastest way to check for not defined parameter is to use typeof value === 'undefined'
rather than doing value === undefined.
*/
t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, // If you don't want to use a thousands separator you can pass empty string as thousands_sep value
sign = (n < 0) ? '-' : '',
// Extracting the absolute value of the integer part of the number and converting to string
i = parseInt(n = Math.abs(n).toFixed(c)) + '',
j = ((j = i.length) > 3) ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
}
И вот несколько тестов:
// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());
// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));
Незначительные изменения:
немного сдвинул Math.abs(decimals)
, чтобы делать только тогда, когда не NaN
.
decimal_sep
больше не может быть пустой строкой (обязательно)
мы используем typeof thousands_sep === 'undefined'
, как предлагается в Как лучше всего определить, не передан ли аргумент функции JavaScript
(+n || 0)
не требуется, потому что this
является Number
объектом
parseInt
вызывается для абсолютного значения целой части числа. Часть INTEGER не может начинаться с ZERO, если только это не просто ZERO! И parseInt(0) === 0
либо восьмеричный, либо десятичный.
- person Marco Demaio; 09.02.2012
0
, считается восьмеричным по parseInt
. Но в этом коде НЕВОЗМОЖНО для parseInt
получить 016
в качестве ввода (или любое другое восьмеричное форматированное значение), потому что аргумент, переданный в parseInt
, является 1-м обработанным функцией Math.abs
. Таким образом, parseInt
не может получить число, начинающееся с нуля, если только это не просто ноль или 0.nn
(где nn
- десятичные числа). Но обе строки 0
и 0.nn
будут преобразованы parseInt
в простой НУЛЬ, как и предполагалось.
- person Marco Demaio; 20.03.2012
(2030).toMoney(0, '.', ' ');
дает следующее: "2 030"
, что является ожидаемым результатом, поскольку вы указываете функции использовать один пробел в качестве разделителя тысяч.
- person Marco Demaio; 31.01.2021
let j = 0;
перед использованием j. Проблемы с кодом у некоторых разработчиков браузеров ... Но в других случаях все еще работает. Странный.
- person JotaPardo; 26.04.2021
Если сумма - это число, скажем -123
, тогда
amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
создаст строку "-$123.00"
.
Вот полный рабочий пример.
minimumFractionDigits: 0
- person Horacio; 29.05.2018
Accounting.js - это крошечная библиотека JavaScript для форматирования чисел, денег и валюты.
Вот лучший форматер денег JavaScript, который я видел:
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) : "");
};
Он был переформатирован и заимствован отсюда: Как отформатировать числа как строки валюты
Вам нужно будет указать свое собственное обозначение валюты (вы использовали $
выше).
Назовите это так (хотя обратите внимание, что аргументы по умолчанию - 2, запятая и точка, поэтому вам не нужно указывать какие-либо аргументы, если вы предпочитаете):
var myMoney = 3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2, ',', '.'); // "$3,543.76"
var
.
- person Jonathan M; 20.11.2013
Вот еще одна попытка, просто для удовольствия:
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
в обратном вызове. Тем не менее, на один обход массива меньше.
- person Wayne; 21.12.2011
reduce
был введен в Ecmascript 1.8 и не поддерживается в Internet Explorer 8 и ниже.
- person Blaise; 10.05.2012
(parseInt(p[0])).toLocaleString()
?
- person Chase Sandmann; 16.06.2015
num=="-" ? acc:
‹br› т.е. функция, переданная в метод уменьшения, будет ‹br› function(acc, num, i, orig) { return num=="-" ? acc:num + (i && !(i % 3) ? "," : "") + acc; }
- person Akshay Vijay Jain; 07.12.2016
Работает для всех текущих браузеров.
Используйте toLocaleString
для форматирования валюты в ее зависимом от языка представлении (используя Коды валют ISO 4217).
(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})
Примеры фрагментов кода южноафриканского рэнда для avenmore:
console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00
(2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2})
- person Nick Grealy; 20.08.2019
minimumFractionDigits: 2
именно то, что я искал!
- person Tim; 24.10.2019
Я думаю, ты хочешь:
f.nettotal.value = "$" + showValue.toFixed(2);
Хорошо, исходя из того, что вы сказали, я использую это:
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 только для того, чтобы сделай это :-) )
Я уже знаю, что должен обнаружить. вместо того, чтобы просто использовать его как десятичный разделитель ...
Numeral.js - библиотека JavaScript для простого форматирования чисел с помощью @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)
Более короткий метод (для вставки пробела, запятой или точки) с регулярным выражением:
Number.prototype.toCurrencyString = function(){
return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g, '$1 ');
}
n = 12345678.9;
alert(n.toCurrencyString());
Следующее краткое, легкое для понимания и не основывается на каких-либо чрезмерно сложных регулярных выражениях.
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)
)
+1 к Джонатану М. за предоставление исходного метода . Поскольку это явно средство форматирования валюты, я пошел дальше и добавил к выходным данным символ валюты (по умолчанию «$») и добавил запятую по умолчанию в качестве разделителя тысяч. Если вам на самом деле не нужен символ валюты (или разделитель тысяч), просто используйте (пустую строку) в качестве аргумента для него.
Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
// check the args and supply defaults:
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
decSeparator = decSeparator == undefined ? "." : decSeparator;
thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;
var n = this,
sign = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return sign + currencySymbol + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
+n || 0
- единственное, что кажется немного странным (по крайней мере, мне).
- person Rich Bradshaw; 18.10.2013
this
- очень полезное имя переменной. Преобразование его в n
, чтобы вы могли сохранить 3 символа во время определения, возможно, было необходимо в эпоху, когда ОЗУ и пропускная способность считались в КБ, но это просто запутывание в эпоху, когда минификатор позаботится обо всем этом, прежде чем он когда-либо попадет в производство. . Остальные умные микрооптимизации по крайней мере спорны.
- person XML; 18.10.2013
Основная часть - это вставка разделителей тысяч, и это можно сделать так:
<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)));">
Есть порт 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 Internet Explorer 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'
Ответ Патрика Дежардена выглядит неплохо, но я предпочитаю простой код 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];
}
В JavaScript есть встроенная функция toFixed:
var num = new Number(349);
document.write("$" + num.toFixed(2));
toFixed()
- person Ian Dunn; 25.09.2012
toFixed()
является функцией объекта Number
и не будет работать с var num
, если он был String
, поэтому мне помог дополнительный контекст.
- person timborden; 20.11.2012
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.
Я предлагаю класс NumberFormat из API визуализации Google.
Вы можете сделать что-то вроде этого:
var formatter = new google.visualization.NumberFormat({
prefix: '$',
pattern: '#,###,###.##'
});
formatter.formatValue(1000000); // $ 1,000,000
Это может быть немного поздно, но вот метод, который я только что разработал для коллеги, чтобы добавить функцию .toCurrencyString()
, учитывающую языковой стандарт, ко всем числам. Интернализация предназначена только для группировки номеров, не знака валюты - если вы выводите доллары, используйте "$"
в том виде, в каком оно было поставлено, потому что $123 4567
в Японии или Китае - это то же количество долларов США, что и $1,234,567
в США. . Если вы выводите евро и т. Д., Измените знак валюты с "$"
.
Объявите это в любом месте вашего HTML-раздела ‹head› или там, где это необходимо, непосредственно перед тем, как вам понадобится его использовать:
Number.prototype.toCurrencyString = function(prefix, suffix) {
if (typeof prefix === 'undefined') { prefix = '$'; }
if (typeof suffix === 'undefined') { suffix = ''; }
var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
}
Тогда все готово! Используйте (number).toCurrencyString()
везде, где вам нужно вывести число в виде валюты.
var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
Как обычно, есть несколько способов сделать одно и то же, но я бы не стал использовать Number.prototype.toLocaleString
, поскольку он может возвращать разные значения в зависимости от настроек пользователя.
Я также не рекомендую расширять Number.prototype
- расширение прототипов собственных объектов является плохой практикой, поскольку может вызвать конфликты с кодом других людей (например, библиотеки / фреймворки / плагины) и может быть несовместимо с будущими реализациями / версиями JavaScript.
Я считаю, что регулярные выражения - лучший способ решения проблемы, вот моя реализация:
/**
* Converts number into currency format
* @param {number} number Number that should be converted.
* @param {string} [decimalSeparator] Decimal separator, defaults to '.'.
* @param {string} [thousandsSeparator] Thousands separator, defaults to ','.
* @param {int} [nDecimalDigits] Number of decimal digits, defaults to `2`.
* @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
*/
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
//default values
decimalSeparator = decimalSeparator || '.';
thousandsSeparator = thousandsSeparator || ',';
nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;
var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]
if(parts){ //number >= 1000 || number <= -1000
return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
}else{
return fixed.replace('.', decimalSeparator);
}
}
Вот некоторые решения, и все они проходят тестовый набор. Набор тестов и тест включены. Если вы хотите скопировать и вставить для проверки, попробуйте эту суть.
Он основан на ответе VisioN, но исправляет если нет десятичной точки.
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's before the first thousands separator
head += (a[0].length - head) % 3 || 3;
a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
return a.join('.');
};
}
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, the browser will stop responding while running.
// This will create a new thread to benchmark
async = [];
function next() {
setTimeout(function () {
f = async.shift();
f && f();
next();
}, 10);
}
console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
Я нашел это из: Accounting.js. Это очень просто и идеально подходит для моих нужд.
// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00
// European formatting (custom symbol and separators), can also use options object as second parameter:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99
// Negative values can be formatted nicely:
accounting.formatMoney(-500000, "£ ", 0); // £ -500,000
// Simple `format` string allows control of symbol position (%v = value, %s = symbol):
accounting.formatMoney(5318008, { symbol: "GBP", format: "%v %s" }); // 5,318,008.00 GBP
// Euro currency symbol to the right
accounting.formatMoney(5318008, {symbol: "€", precision: 2, thousand: ".", decimal : ",", format: "%v%s"}); // 1.008,00€
$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );
- показать 1.000,00 E
- person ; 07.06.2017
Простой вариант для правильного размещения запятой, сначала поменяв местами строку и базовое регулярное выражение.
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();
};
Кодовая база 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 it unaltered
else {
return nData;
}
}
Это потребует редактирования, поскольку библиотека YUI настраивается, например, замена oConfig.decimalSeparator на ..
Пример Патрика Дежардена (бывшего Даока) хорошо мне подошел. Я перенес его на 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
Минималистичный подход, отвечающий первоначальным требованиям:
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];
}
tggagne верен. Мое решение ниже не подходит из-за округления с плавающей запятой. А функции toLocaleString не хватает поддержки браузером. Я оставлю нижеприведенные комментарии в целях архивации того, что не делать. :)
Date.prototype.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 });
}
См. Интернационализация и локализация, Валюты для получения дополнительной информации.
Функция для обработки вывода валюты, включая негативы.
Пример вывода:
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();
}
Другой путь:
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;
}
Мы также можем использовать numeraljs.
Числа можно отформатировать так, чтобы они выглядели как валюта, проценты, времена или даже простые старые числа с десятичными знаками, тысячами и сокращениями. И вы всегда можете создать собственный формат.
var string = numeral(1000).format('0,0');
// '1,000'
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;
}
var number = 3500;
alert(new Intl.NumberFormat().format(number));
// → "3,500" if in US English locale
Или number_format PHP в JavaScript.
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 (новый Intl.NumberFormat ('ar-EG'). Format (number)); // → ١٢٣٤٥٦ ٫ ٧٨٩
// В Индии используются разделители тысяч / миллионов / кроров console.log (новый Intl.NumberFormat ('en-IN'). Format (number));
Этот ответ соответствует следующим критериям:
Этот код основан на концепциях из других ответов. Его скорость выполнения должна быть среди лучших, если это вызывает беспокойство.
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 + "\"");
}
}
Вот краткий и лучший способ конвертировать числа в денежный формат:
function toCurrency(amount){
return amount.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
// usage: toCurrency(3939920.3030);
toCurrency('123456.7890')
возвращает 123,456.7,890
. ИМХО, в десятичных разрядах не должно быть запятых. В остальном выглядит хорошо!
- person Mike Causer; 24.04.2014
Код от Джонатана М выглядел для меня слишком сложным , поэтому я переписал его и получил около 30% на Firefox 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"
toLocaleString - это хорошо, но работает не во всех браузерах. Обычно я использую currencyFormatter.js (https://osrec.github.io/currencyFormatter.js/ а>). Он довольно легкий и содержит все определения валюты и локали прямо из коробки. Он также хорош для форматирования необычно отформатированных валют, таких как INR (в котором числа группируются в lakhs, кроры и т. Д.). Также нет никаких зависимостей!
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 €
Это может сработать:
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));
}
Никаких циклов, никаких регулярных выражений, никаких массивов, никаких экзотических условных выражений.
В JavaScript нет эквивалента formatNumber. Вы можете написать это сами или найти библиотеку, которая уже это делает.
Вот реализация 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) : '');
});
Более быстрый способ с регулярным выражением:
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;
}
Я во многом основывал это на ответе 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
Просто для развлечения.
Мне нравится самый короткий ответ VisionN, кроме случаев, когда я необходимо изменить его на число без десятичной точки (123 доллара вместо 123 долларов). Это не работает, поэтому вместо быстрого копирования / вставки мне нужно расшифровать загадочный синтаксис регулярного выражения 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
)?=
...) (взгляд вперед)\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 долларов), мы можем изменить регулярное выражение следующим образом:
var re2 = /\d(?=(\d{3})+$)/g;
Он полагается на конец строки ($
) вместо точки (\.
), и окончательное выражение будет (обратите внимание также на toFixed(0)
):
n.toFixed(0).replace(/\d(?=(\d{3})+$)/g, '$&,');
Это выражение даст
1234567.89 -> 1,234,567
Кроме того, вместо конца строки ($
) в регулярном выражении выше вы также можете выбрать границу слова (\b
).
Приношу свои извинения заранее, если я неверно истолковал какую-либо часть обработки регулярных выражений.
Многие ответы содержали полезные идеи, но ни один из них не соответствовал моим потребностям. Итак, я использовал все идеи и построил этот пример:
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, for example: var _f_octal = function( v_in,...){
//--------------------------------
if(typeof(fmt) !== "undefined"){
//...can be extended..., just add the char, for example "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..., for example: 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 €).
Помимо гибкости, мне требовалось очень быстрое решение для обработки таблиц. Это означает, что при обработке тысяч ячеек обработка строки формата не должна выполняться более одного раза. Формат, подобный вызову (значение, 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 включает регулярное выражение;
В-третьих, формат, подобный вызову (значение, fmt), неприемлем, потому что:
Хотя должна быть возможность форматировать разные коллекции объектов (например, ячейки столбца) с разными масками, я не хочу иметь что-то для обработки строк форматирования в точке обработки. На данный момент я хочу только использовать форматирование, как в
for (ячейка var в ячейках) {do_something (cell.col.formatter (cell.value)); }
Какой формат - может быть, он определен в файле .ini, в XML для каждого столбца или где-то еще ..., но анализ и установка форматов или работа с интернационализацией обрабатывается совершенно в другом месте , и здесь я хочу назначить средство форматирования для коллекции, не задумываясь о проблемах с производительностью:
col.formatter = Format_Numb (_getFormatForColumn (...));
В-четвертых, мне нужно терпимое решение, поэтому передача, например, строки вместо числа должна возвращать просто строку, а значение 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();
Хотя я тестировал некоторые, в коде может быть много ошибок. Так что это не готовый модуль, а всего лишь идея и отправная точка для таких экспертов, не связанных с JavaScript, как я.
Код содержит множество и немного измененных идей из множества сообщений о переполнении стека; извините, я не могу сослаться на все из них, но спасибо всем экспертам.
l=l-v.length
(находится в логическом контексте / сравнение), return "\"+"+f+"+\"";
(отсутствуют экраны?) И return new Function("_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex);
(это допустимый синтаксис? - нет риторический вопрос).
- person Peter Mortensen; 27.05.2021
Мне было трудно найти простую библиотеку для работы с датой и валютой, поэтому я создал свою: https://github.com/dericeira/slimFormatter.js
Просто как тот:
var number = slimFormatter.currency(2000.54);
Потому что каждая проблема заслуживает решения в одну строку:
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
Я хотел ванильное решение 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");
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 - Internet Explorer also puts in .00, so we'll get 12,345,678.00
// If Internet Explorer (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));
Это работает в Firefox и Internet Explorer.
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 "")
Я хочу внести свой вклад в это:
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>
<script language=="Javascript">
допустимый синтаксис (не риторический вопрос)?
- person Peter Mortensen; 27.05.2021
theEvent.preventDefault
и theEvent.preventDefault()
? (Используется в той же конструкции)
- person Peter Mortensen; 27.05.2021
Вот простой форматировщик на ванильном JavaScript:
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 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 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("");
}
Взяв несколько из лучших ответов, я объединил и составил ECMAScript 2015 (ES6), которая передает ESLint.
export const formatMoney = (
amount,
decimalCount = 2,
decimal = '.',
thousands = ',',
currencySymbol = '$',
) => {
if (typeof Intl === 'object') {
return new Intl.NumberFormat('en-AU', {
style: 'currency',
currency: 'AUD',
}).format(amount);
}
// Fallback if Intl is not present.
try {
const negativeSign = amount < 0 ? '-' : '';
const amountNumber = Math.abs(Number(amount) || 0).toFixed(decimalCount);
const i = parseInt(amountNumber, 10).toString();
const j = i.length > 3 ? i.length % 3 : 0;
return (
currencySymbol +
negativeSign +
(j ? i.substr(0, j) + thousands : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, `$1${thousands}`) +
(decimalCount
? decimal +
Math.abs(amountNumber - i)
.toFixed(decimalCount)
.slice(2)
: '')
);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
return amount;
};
Уже есть хорошие ответы. Вот простая попытка развлечься:
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)
)
ar[0] | 0
?
- person Peter Mortensen; 27.05.2021
Пожалуйста, найдите в приведенном ниже коде то, что я разработал для поддержки интернационализации.
Он форматирует данное числовое значение в формат, специфичный для языка. В данном примере я использовал 'en', в то время как тестировал 'es', 'fr' и другие страны, где формат варьируется . Он не только не позволяет пользователю вводить символы, но и форматирует значение при выводе табуляции.
Я создал компоненты для Числового, а также для Десятичного формата. Помимо этого, я создал функции parseNumber (значение, языковой стандарт) и parseDecimal (значение, языковой стандарт), которые будут анализировать отформатированные данные для любых других бизнес-целей. Указанная функция примет форматированные данные и вернет неформатированное значение. Я использовал плагин валидатора jQuery в приведенном ниже общем коде.
HTML:
<tr>
<td>
<label class="control-label">
Number Field:
</label>
<div class="inner-addon right-addon">
<input type="text" id="numberField"
name="numberField"
class="form-control"
autocomplete="off"
maxlength="17"
data-rule-required="true"
data-msg-required="Cannot be blank."
data-msg-maxlength="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
data-rule-numberExceedsMaxLimit="en"
data-msg-numberExceedsMaxLimit="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
onkeydown="return isNumber(event, 'en')"
onkeyup="return updateField(this)"
onblur="numberFormatter(this,
'en',
'Invalid character(s) found. Please enter valid characters.')">
</div>
</td>
</tr>
<tr>
<td>
<label class="control-label">
Decimal Field:
</label>
<div class="inner-addon right-addon">
<input type="text" id="decimalField"
name="decimalField"
class="form-control"
autocomplete="off"
maxlength="20"
data-rule-required="true"
data-msg-required="Cannot be blank."
data-msg-maxlength="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
data-rule-decimalExceedsMaxLimit="en"
data-msg-decimalExceedsMaxLimit="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
onkeydown="return isDecimal(event, 'en')"
onkeyup="return updateField(this)"
onblur="decimalFormatter(this,
'en',
'Invalid character(s) found. Please enter valid characters.')">
</div>
</td>
</tr>
JavaScript:
/*
* @author: dinesh.lomte
*/
/* Holds the maximum limit of digits to be entered in number field. */
var numericMaxLimit = 13;
/* Holds the maximum limit of digits to be entered in decimal field. */
var decimalMaxLimit = 16;
/**
*
* @param {type} value
* @param {type} locale
* @returns {Boolean}
*/
parseDecimal = function(value, locale) {
value = value.trim();
if (isNull(value)) {
return 0.00;
}
if (isNull(locale)) {
return value;
}
if (getNumberFormat(locale)[0] === '.') {
value = value.replace(/\./g, '');
} else {
value = value.replace(
new RegExp(getNumberFormat(locale)[0], 'g'), '');
}
if (getNumberFormat(locale)[1] === ',') {
value = value.replace(
new RegExp(getNumberFormat(locale)[1], 'g'), '.');
}
return value;
};
/**
*
* @param {type} element
* @param {type} locale
* @param {type} nanMessage
* @returns {Boolean}
*/
decimalFormatter = function (element, locale, nanMessage) {
showErrorMessage(element.id, false, null);
if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
return true;
}
var value = element.value.trim();
value = value.replace(/\s/g, '');
value = parseDecimal(value, locale);
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 2,
maximumFractionDigits: 2
}
);
if (numberFormatObj.format(value) === 'NaN') {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
element.value = numberFormatObj.format(value);
return true;
};
/**
*
* @param {type} element
* @param {type} locale
* @param {type} nanMessage
* @returns {Boolean}
*/
numberFormatter = function (element, locale, nanMessage) {
showErrorMessage(element.id, false, null);
if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
return true;
}
var value = element.value.trim();
var format = getNumberFormat(locale);
if (hasDecimal(value, format[1])) {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
value = value.replace(/\s/g, '');
value = parseNumber(value, locale);
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 0,
maximumFractionDigits: 0
}
);
if (numberFormatObj.format(value) === 'NaN') {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
element.value =
numberFormatObj.format(value);
return true;
};
/**
*
* @param {type} id
* @param {type} flag
* @param {type} message
* @returns {undefined}
*/
showErrorMessage = function(id, flag, message) {
if (flag) {
// only add if not added
if ($('#'+id).parent().next('.app-error-message').length === 0) {
var errorTag = '<div class=\'app-error-message\'>' + message + '</div>';
$('#'+id).parent().after(errorTag);
}
} else {
// remove it
$('#'+id).parent().next(".app-error-message").remove();
}
};
/**
*
* @param {type} id
* @returns
*/
setFocus = function(id) {
id = id.trim();
if (isNull(id)) {
return;
}
setTimeout(function() {
document.getElementById(id).focus();
}, 10);
};
/**
*
* @param {type} value
* @param {type} locale
* @returns {Array}
*/
parseNumber = function(value, locale) {
value = value.trim();
if (isNull(value)) {
return 0;
}
if (isNull(locale)) {
return value;
}
if (getNumberFormat(locale)[0] === '.') {
return value.replace(/\./g, '');
}
return value.replace(
new RegExp(getNumberFormat(locale)[0], 'g'), '');
};
/**
*
* @param {type} locale
* @returns {Array}
*/
getNumberFormat = function(locale) {
var format = [];
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 2,
maximumFractionDigits: 2
}
);
var value = numberFormatObj.format('132617.07');
format[0] = value.charAt(3);
format[1] = value.charAt(7);
return format;
};
/**
*
* @param {type} value
* @param {type} fractionFormat
* @returns {Boolean}
*/
hasDecimal = function(value, fractionFormat) {
value = value.trim();
if (isNull(value) || isNull(fractionFormat)) {
return false;
}
if (value.indexOf(fractionFormat) >= 1) {
return true;
}
};
/**
*
* @param {type} event
* @param {type} locale
* @returns {Boolean}
*/
isNumber = function(event, locale) {
var keyCode = event.which ? event.which : event.keyCode;
// Validating if user has pressed shift character
if (keyCode === 16) {
return false;
}
if (isNumberKey(keyCode)) {
return true;
}
var numberFormatter = [32, 110, 188, 190];
if (keyCode === 32
&& isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
return true;
}
if (numberFormatter.indexOf(keyCode) >= 0
&& getNumberFormat(locale)[0] === getFormat(keyCode)) {
return true;
}
return false;
};
/**
*
* @param {type} event
* @param {type} locale
* @returns {Boolean}
*/
isDecimal = function(event, locale) {
var keyCode = event.which ? event.which : event.keyCode;
// Validating if user has pressed shift character
if (keyCode === 16) {
return false;
}
if (isNumberKey(keyCode)) {
return true;
}
var numberFormatter = [32, 110, 188, 190];
if (keyCode === 32
&& isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
return true;
}
if (numberFormatter.indexOf(keyCode) >= 0
&& (getNumberFormat(locale)[0] === getFormat(keyCode)
|| getNumberFormat(locale)[1] === getFormat(keyCode))) {
return true;
}
return false;
};
/**
*
* @param {type} keyCode
* @returns {Boolean}
*/
isNumberKey = function(keyCode) {
if ((keyCode >= 48 && keyCode <= 57) ||
(keyCode >= 96 && keyCode <= 105)) {
return true;
}
var keys = [8, 9, 13, 35, 36, 37, 39, 45, 46, 109, 144, 173, 189];
if (keys.indexOf(keyCode) !== -1) {
return true;
}
return false;
};
/**
*
* @param {type} keyCode
* @returns {JSON@call;parse.numberFormatter.value|String}
*/
getFormat = function(keyCode) {
var jsonString = '{"numberFormatter" : [{"key":"32", "value":" ", "description":"space"}, {"key":"188", "value":",", "description":"comma"}, {"key":"190", "value":".", "description":"dot"}, {"key":"110", "value":".", "description":"dot"}]}';
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.numberFormatter) {
if (jsonObject.numberFormatter.hasOwnProperty(key)
&& keyCode === parseInt(jsonObject.numberFormatter[key].key)) {
return jsonObject.numberFormatter[key].value;
}
}
return '';
};
/**
*
* @type String
*/
var jsonString = '{"shiftCharacterNumberMap" : [{"char":")", "number":"0"}, {"char":"!", "number":"1"}, {"char":"@", "number":"2"}, {"char":"#", "number":"3"}, {"char":"$", "number":"4"}, {"char":"%", "number":"5"}, {"char":"^", "number":"6"}, {"char":"&", "number":"7"}, {"char":"*", "number":"8"}, {"char":"(", "number":"9"}]}';
/**
*
* @param {type} value
* @returns {JSON@call;parse.shiftCharacterNumberMap.number|String}
*/
getShiftCharSpecificNumber = function(value) {
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.shiftCharacterNumberMap) {
if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
&& value === jsonObject.shiftCharacterNumberMap[key].char) {
return jsonObject.shiftCharacterNumberMap[key].number;
}
}
return '';
};
/**
*
* @param {type} value
* @returns {Boolean}
*/
isShiftSpecificChar = function(value) {
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.shiftCharacterNumberMap) {
if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
&& value === jsonObject.shiftCharacterNumberMap[key].char) {
return true;
}
}
return false;
};
/**
*
* @param {type} element
* @returns {undefined}
*/
updateField = function(element) {
var value = element.value;
for (var index = 0; index < value.length; index++) {
if (!isShiftSpecificChar(value.charAt(index))) {
continue;
}
element.value = value.replace(
value.charAt(index),
getShiftCharSpecificNumber(value.charAt(index)));
}
};
/**
*
* @param {type} value
* @param {type} element
* @param {type} params
*/
jQuery.validator.addMethod('numberExceedsMaxLimit', function(value, element, params) {
value = parseInt(parseNumber(value, params));
if (value.toString().length > numericMaxLimit) {
showErrorMessage(element.id, false, null);
setFocus(element.id);
return false;
}
return true;
}, 'Exceeding the maximum limit of 13 digits. Example: 1234567890123.');
/**
*
* @param {type} value
* @param {type} element
* @param {type} params
*/
jQuery.validator.addMethod('decimalExceedsMaxLimit', function(value, element, params) {
value = parseFloat(parseDecimal(value, params)).toFixed(2);
if (value.toString().substring(
0, value.toString().lastIndexOf('.')).length > numericMaxLimit
|| value.toString().length > decimalMaxLimit) {
showErrorMessage(element.id, false, null);
setFocus(element.id);
return false;
}
return true;
}, 'Exceeding the maximum limit of 16 digits. Example: 1234567890123.00.');
/**
* @param {type} id
* @param {type} locale
* @returns {boolean}
*/
isNumberExceedMaxLimit = function(id, locale) {
var value = parseInt(parseNumber(
document.getElementById(id).value, locale));
if (value.toString().length > numericMaxLimit) {
setFocus(id);
return true;
}
return false;
};
/**
* @param {type} id
* @param {type} locale
* @returns {boolean}
*/
isDecimalExceedsMaxLimit = function(id, locale) {
var value = parseFloat(parseDecimal(
document.getElementById(id).value, locale)).toFixed(2);
if (value.toString().substring(
0, value.toString().lastIndexOf('.')).length > numericMaxLimit
|| value.toString().length > decimalMaxLimit) {
setFocus(id);
return true;
}
return false;
};
Крошечная библиотека JavaScript с нулевой зависимостью (1 Кбайт) от CurrencyRate.today, обеспечивающая простой способ и расширенное форматирование чисел, денег и валюты, удаляет все форматирование / мусор и возвращает необработанное значение с плавающей запятой.
https://github.com/dejurin/format-money-js
npm install format-money-js
Функции:
from: форматирование денег и валюты;
un: удаляет все форматирование / беспорядок и возвращает необработанное значение с плавающей запятой.
Примеры 1
const { FormatMoney } = require('format-money-js');
const fm = new FormatMoney({
decimals: 2
});
console.log(fm.from(12345.67, { symbol: '$' })); // return string: $12,345.67
console.log(fm.un('€12,345;67')); // return number: 12345.67
Пример 2
const { FormatMoney } = require('format-money-js');
const fm = new FormatMoney({
decimals: 2
});
console.log(fm.from(
12345.67,
{ symbol: '$' },
true // Parse, return object
)
);
/* return object:
{
source: 12345.67,
negative: false,
fullAmount: '12,345.67',
amount: '12,345',
decimals: '.67',
symbol: '$'
}*/
Вот быстрый способ использования regexp и replace.
function formatCurrency(number, dp, ts) {
var num = parseFloat(number); // Convert to float
var pw; // For Internet Explorer
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 Internet Explorer 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 fixing Internet Explorer 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 separator and rejoin all parts
} );
}
($#,##0.00)
указываются отрицательные суммы валюты. - person einstein   schedule 26.10.2014