Как я могу отформатировать числа в виде строки валюты долларов в JavaScript?

1501

Я хотел бы отформатировать цену в JavaScript.
Мне нужна функция, которая принимает float в качестве аргумента и возвращает формат string следующим образом:

"$ 2,500.00"

Какой лучший способ сделать это?

  • 0
    Желательно, не обязательно. Я только что опубликовал ответ, который, я думаю, основан на предложениях людей
  • 8
    В javascript нет встроенной функции formatNumber
Показать ещё 19 комментариев
Теги:
formatting
currency

64 ответа

25
Лучший ответ

Хорошо, основываясь на том, что вы сказали, я использую это:

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 только для этого:-)) Я уже знаю, что должен обнаруживать "." вместо того, чтобы просто использовать его как десятичный разделитель...

  • 7
    Обратите внимание, что ваша версия не округляется до двух десятичных цифр. Например, 3.706 будет отформатирован как «£ 3.70», а не как «£ 3.71», как это должно быть.
  • 0
    Да, это нормально в моем конкретном случае, поскольку суммы, с которыми я работаю, уже имеют не более 2 цифр. Причина, по которой мне нужно установить значение до 2 десятичных знаков, относится к суммам без десятичных знаков или только с 1.
1581

Number.prototype.toFixed

Это решение совместимо с каждым основным браузером:

  const profits = 2489.8237;

  profits.toFixed(3) //returns 2489.824 (rounds up)
  profits.toFixed(2) //returns 2489.82
  profits.toFixed(7) //returns 2489.8237000 (pads the decimals)

Все, что вам нужно, это добавить символ валюты (например, "$" + profits.toFixed(2)), и вы получите свою сумму в долларах.

Пользовательская функция

Если вам требуется использование , между каждой цифрой, вы можете использовать эту функцию:

function formatMoney(n, c, d, t) {
  var c = isNaN(c = Math.abs(c)) ? 2 : c,
    d = d == undefined ? "." : d,
    t = t == undefined ? "," : t,
    s = n < 0 ? "-" : "",
    i = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(c))),
    j = (j = i.length) > 3 ? j % 3 : 0;

  return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};

document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>

Используйте это так:

(123456789.12345).formatMoney(2, ".", ",");

Если вы всегда собираетесь использовать "." и ',', вы можете оставить их вне вызова метода, и метод по умолчанию выберет их для вас.

(123456789.12345).formatMoney(2);

Если в вашей культуре два символа перевернуты (т. formatMoney Европейцы), и вы хотите использовать значения по умолчанию, просто вставьте следующие две строки в методе formatMoney:

    d = d == undefined ? "," : d, 
    t = t == undefined ? "." : t, 

Пользовательская функция (ES6)

Если вы можете использовать современный синтаксис ECMAScript (например, через Babel), вы можете использовать эту простую функцию вместо этого:

function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
  try {
    decimalCount = Math.abs(decimalCount);
    decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

    const negativeSign = amount < 0 ? "-" : "";

    let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
    let j = (i.length > 3) ? i.length % 3 : 0;

    return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
  } catch (e) {
    console.log(e)
  }
};
document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>
  • 2
    Если вы всегда хотите округлить до 5 и ниже 5, вы не можете полагаться на toFixed () из-за стандартных проблем, связанных с представлением с плавающей запятой в двоичном виде. Например, попробуйте (1.005).toFixed(2) .
  • 26
    прежде всего отличный, лаконичный код. однако, если вы американец, вы должны изменить значения по умолчанию d и t на . и , соответственно, чтобы вам не приходилось указывать их каждый раз. Кроме того, я рекомендую изменить начало оператора return образом: return s + '$' + [rest] , иначе вы не получите знак доллара.
Показать ещё 35 комментариев
1174

Короткое и быстрое решение (работает везде!)

(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');  // 12,345.67

Идея этого решения заключается в замене согласованных разделов первым совпадением и запятой, то есть '$&,'. Согласование выполняется с использованием метода lookahead. Вы можете прочитать выражение как "соответствовать числу, если за ним следует последовательность из трех наборов чисел (одна или несколько) и точка".

ИСПЫТАНИЯ:

1        --> "1.00"
12       --> "12.00"
123      --> "123.00"
1234     --> "1,234.00"
12345    --> "12,345.00"
123456   --> "123,456.00"
1234567  --> "1,234,567.00"
12345.67 --> "12,345.67"

ДЕМО: http://jsfiddle.net/hAfMM/9571/


Расширенное короткое решение

Вы также можете расширить прототип объекта Number чтобы добавить дополнительную поддержку любого количества десятичных знаков [0.. n] и размера групп чисел [0.. x]:

/**
 * Number.prototype.format(n, x)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of sections
 */
Number.prototype.format = function(n, x) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};

1234..format();           // "1,234"
12345..format(2);         // "12,345.00"
123456.7.format(3, 2);    // "12,34,56.700"
123456.789.format(2, 4);  // "12,3456.79"

ДЕМО/ИСПЫТАНИЯ: http://jsfiddle.net/hAfMM/435/


Супер расширенное короткое решение

В этой расширенной версии вы можете установить разные типы разделителей:

/**
 * Number.prototype.format(n, x, s, c)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of whole part
 * @param mixed   s: sections delimiter
 * @param mixed   c: decimal delimiter
 */
Number.prototype.format = function(n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
        num = this.toFixed(Math.max(0, ~~n));

    return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};

12345678.9.format(2, 3, '.', ',');  // "12.345.678,90"
123456.789.format(4, 4, ' ', ':');  // "12 3456:7890"
12345678.9.format(0, 3, '-');       // "12-345-679"

ДЕМО/ИСПЫТАНИЯ: http://jsfiddle.net/hAfMM/612/

  • 14
    На самом деле я пошел еще дальше: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,") .
  • 3
    Версия CoffeeScript с регулярным выражением VisioN & kalisjoshua и способом указания десятичного знака (так что вы можете оставить значение по умолчанию 2 или указать 0 без десятичного знака): Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Показать ещё 31 комментарий
911

Intl.numberformat

Javascript имеет средство форматирования чисел (часть Интернационализации API).

// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  // the default value for minimumFractionDigits depends on the currency
  // and is usually already 2
});

formatter.format(2500); /* $2,500.00 */

JS скрипка

Используйте undefined вместо первого аргумента (в данном примере 'en-US'), чтобы использовать языковой стандарт системы (языковой стандарт пользователя в случае, если код выполняется в браузере).

Intl.NumberFormat vs Number.prototype.toLocaleString

Последнее замечание, сравнивающее это со старшим. toLocaleString. Они оба предлагают по существу одинаковую функциональность. Однако toLocaleString в его более старых версиях (pre-Intl) фактически не поддерживает локали: он использует системную локаль. Поэтому, чтобы убедиться, что вы используете правильную версию, MDN предлагает проверить наличие Intl. Так что, если вам все равно нужно проверить Intl, почему бы не использовать его вместо этого? Однако, если вы решите использовать toLocaleString, он также исправляет toLocaleString, поэтому в этом случае вы можете использовать его без каких-либо хлопот:

(2500).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD',
}); /* $2,500.00 */

Несколько замечаний по поддержке браузера

  • Поддержка браузеров в настоящее время больше не является проблемой с поддержкой 97% в США/ЕС.
  • Для других частей мира (поддержка 90%) самыми большими нарушителями в плане поддержки являются UC Mobile (держитесь подальше от этого) и Opera Mini (покалеченные дизайном)
  • Существует прокладка, чтобы поддержать его на старых браузерах
  • Посмотрите на CanIUse для получения дополнительной информации
  • 52
    Это идиоматическое JavaScript, простое и элегантное решение - именно то, что я искал.
  • 8
    ненадежный на сафари
Показать ещё 24 комментария
189

Взгляните на объект JavaScript Number и посмотрите, может ли он вам помочь.

  • toLocaleString() будет отформатировать число, используя разделитель тысяч тысяч адресов.
  • toFixed() будет округлять число до определенного числа десятичных знаков.

Чтобы использовать их одновременно, значение должно иметь свой тип, измененный обратно на число, потому что они оба выводят строку.

Пример:

Number(someNumber.toFixed(1)).toLocaleString()
  • 2
    Спасибо! Основываясь на этой идее, я смог сделать ее достаточно короткой и простой! (и локализовано) Отлично.
  • 5
    На самом деле Вы можете. т.е. для долларов: '$' + (значение + 0,001) .toLocaleString (). slice (0, -1)
Показать ещё 9 комментариев
157

Ниже приведен код Patrick Desjardins (псевдоним Daok) с небольшим количеством добавленных комментариев и некоторыми незначительными изменениями:

/* 
decimal_sep: character used as deciaml separtor, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{ 
   var n = this,
   c = isNaN(decimals) ? 2 : Math.abs(decimals), //if decimal is zero we must take it, it means user does not want to show any decimal
   d = decimal_sep || '.', //if no decimal separator is passed we use the dot as default decimal separator (we MUST use a decimal separator)

   /*
   according to [/questions/3130/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
   the fastest way to check for not defined parameter is to use typeof value === 'undefined' 
   rather than doing value === undefined.
   */   
   t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, //if you don't want to use a thousands separator you can pass empty string as thousands_sep value

   sign = (n < 0) ? '-' : '',

   //extracting the absolute value of the integer part of the number and converting to string
   i = parseInt(n = Math.abs(n).toFixed(c)) + '', 

   j = ((j = i.length) > 3) ? j % 3 : 0; 
   return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); 
}

и вот несколько тестов:

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());

//some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));

Незначительные изменения:

  1. немного Math.abs(decimals) чтобы сделать это только тогда, когда не NaN.

  2. decimal_sep больше не может быть пустой строкой (decimal_sep какой-то десятичный разделитель)

  3. мы используем typeof thousands_sep === 'undefined' как предложено в разделе Как лучше всего определить, не передается ли аргумент в функцию JavaScript

  4. (+n || 0) не нужен, потому что this объект Number

JS Fiddle

  • 8
    Вы можете использовать '10' в качестве основы в parseInt. В противном случае любое число, начинающееся с «0», будет использовать восьмеричную нумерацию.
  • 3
    @ sohtimsso1970: извините за поздний ответ, но не могли бы вы объяснить еще? Я не понимаю, где число можно интерпретировать как восьмеричное. parseInt вызывается по абсолютному значению части числа INTEGER. Партия INTEGER не может начинаться с нуля, если только это не ноль! И parseInt(0) === 0 восьмеричный или десятичный.
Показать ещё 3 комментария
121

accounting.js - это крошечная библиотека JavaScript для форматирования чисел, денег и валюты.

  • 0
    ... просто не забудьте передать символ валюты, в противном случае ошибки в IE7 и IE8, IE9 в любом случае хорошо
  • 2
    Похоже, ошибка IE7 / IE8 исправлена.
Показать ещё 5 комментариев
101

Если количество - это число, скажем -123, тогда

amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' });

"-$123.00" строку "-$123.00".

Вот полный рабочий пример.

  • 7
    Этот ответ был почти для меня, но мне нужно было округлить его до ближайшей копейки. Это то, что я использовал сумма.toLocaleString ('en-GB', {стиль: 'валюта', валюта: 'GBP', MaximumFractionDigits: 2});
  • 0
    Приведенный выше код выполняет округление до нужного количества цифр. Смотрите пример и введите 1.237 в поле ввода.
Показать ещё 4 комментария
92

Здесь лучший форматировщик js money, который я видел:

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
    var n = this,
        decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
        decSeparator = decSeparator == undefined ? "." : decSeparator,
        thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;
    return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};

Он был переформатирован и заимствован отсюда: https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-dollars-currency-string-in-javascript

Вам нужно будет указать свой собственный валютный указатель (вы использовали $выше).

Назовите его так (хотя обратите внимание, что аргументы по умолчанию равны 2, запятой и периоду, поэтому вам не нужно указывать какие-либо аргументы, если вы предпочитаете):

var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"
  • 0
    Остерегайтесь глобальных знаков, я, J
  • 6
    @hacklikecrack, все переменные являются локальными; они в утверждении var .
Показать ещё 2 комментария
68

Здесь уже есть отличные ответы. Вот еще одна попытка, просто для удовольствия:

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"

Отредактировано: теперь он будет обрабатывать и отрицательные числа

  • 0
    поэзия. блестящий. Вы пробовали использовать limitRight () developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…, который должен устранить обратную ()?
  • 1
    @ Steve - Вы правы, но вам нужно сделать что-то вроде i = orig.length - i - 1 в i = orig.length - i - 1 . Тем не менее, еще один обход массива.
Показать ещё 9 комментариев
65

Я думаю, что вы хотите f.nettotal.value = "$" + showValue.toFixed(2);

  • 0
    @ раздавить это работает, но это больше не переносит расчеты в поле налога?
  • 11
    После того, как вы добавите к нему знак $, это уже не число, а строка.
61

Так почему же никто не предложил следующее?

(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2}) 

Работает для большинства/некоторых браузеров:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString#Browser_Compatibility

  • 1
    Поскольку аргументы «locales» и «options» поддерживаются очень небольшим количеством браузеров, таких как Chrome 24, IE11 и Opera 15. Firefox, Safari и более ранние версии других по-прежнему не поддерживают его.
  • 3
    Согласитесь, это не полностью поддерживается во всех браузерах (пока), но это все еще решение. (И, пожалуй, самое правильное решение, так как оно совместимо с неподдерживаемыми браузерами и является документированной функцией API Javascript.)
Показать ещё 5 комментариев
25

Numeral.js - библиотека js для легкого форматирования чисел от @adamwdraper

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
  • 0
    это потрясающе спасибо
  • 0
    Вилка Numbro, кажется, получает больше любви, поскольку Numeral.js кажется заброшенным: github.com/foretagsplatsen/numbro
Показать ещё 1 комментарий
24

Я использую библиотеку Globalize (от Microsoft):

Это отличный проект для локализации чисел, валют и дат и автоматического их форматирования в соответствии с пользовательским языком!... и, несмотря на это, должно быть расширение jQuery, в настоящее время это 100% независимая библиотека. Я предлагаю вам все попробовать!:)

  • 3
    Вау, почему это не проголосовало больше? Большая стандартизированная библиотека для всех видов форматирования. Стандартные параметры форматирования с правильной глобализацией. Отличный ответ !!
  • 0
    Это все еще считается альфа-стадией, поэтому используйте осторожно, но отличная находка.
Показать ещё 1 комментарий
23

javascript-number-formatter (ранее на Google Code)

  • Короткий, быстрый, гибкий, но автономный. Только 75 строк, включая информацию о лицензии MIT, пустые строки и комментарии.
  • Принять стандартное форматирование номера, например #,##0.00 или с отрицанием -000.####.
  • Примите любой формат страны, например # ##0,00, #,###.##, #'###.## или любой символ без нумерации.
  • Принять любые цифры группировки цифр. #,##,#0.000 или #,###0.## являются действительными.
  • Принять любое форматирование с избыточным/безумным подтверждением. ##,###,##.# или 0#,#00#.###0# все в порядке.
  • Автоматическое округление номеров.
  • Простой интерфейс, просто установите маску и значение следующим образом: format( "0.0000", 3.141592).
  • Включить префикс и суффикс с маской

(выдержка из его README)

21

+1 к Jonathan M для предоставления исходного метода. Так как это явно форматирование валюты, я пошел вперед и добавил символ валюты (по умолчанию "$" ) к выходу и добавил запятую по умолчанию в качестве разделителя тысяч. Если вам действительно не нужен символ валюты (или разделитель тысяч), просто используйте "" (пустую строку) в качестве аргумента для него.

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator, currencySymbol) {
    // check the args and supply defaults:
    decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
    decSeparator = decSeparator == undefined ? "." : decSeparator;
    thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
    currencySymbol = currencySymbol == undefined ? "$" : currencySymbol;

    var n = this,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;

    return sign + currencySymbol + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
  • 0
    Первый вариант довольно странный, так как эти переменные уже объявлены в объявлении функции. Кроме этого, спасибо!
  • 2
    Ты прав. Это ошибка, которую я привел из оригинала Джонатана М., где все они связаны как одно выражение var. Это должны быть простые задания. Закрепление.
Показать ещё 6 комментариев
19

Более короткий метод (для вставки пробела, запятой или точкой) с регулярным выражением?

    Number.prototype.toCurrencyString=function(){
        return this.toFixed(2).replace(/(\d)(?=(\d{3})+\b)/g,'$1 ');
    }

    n=12345678.9;
    alert(n.toCurrencyString());
19

Существует javascript-порт функции PHP "number_format".

Я нахожу его очень полезным, поскольку он прост в использовании и узнаваем для разработчиков PHP.

function number_format (number, decimals, dec_point, thousands_sep) {
    var n = number, prec = decimals;

    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };

    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); 
    //fix for IE parseFloat(0.55).toFixed(0) = 0;

    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;

    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;

        _[0] = s.slice(0,i + (n < 0)) +
               _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }

    var decPos = s.indexOf(dec);
    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
    }
    else if (prec >= 1 && decPos === -1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s; 
}

(блок комментариев из оригинал, приведенный ниже для примеров и кредитов, где это необходимо)

// Formats a number with grouped thousands
//
// version: 906.1806
// discuss at: http://phpjs.org/functions/number_format
// +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// +     bugfix by: Michael White (http://getsprink.com)
// +     bugfix by: Benjamin Lupton
// +     bugfix by: Allan Jensen (http://www.winternet.no)
// +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
// +     bugfix by: Howard Yeend
// +    revised by: Luke Smith (http://lucassmith.name)
// +     bugfix by: Diogo Resende
// +     bugfix by: Rival
// +     input by: Kheang Hok Chin (http://www.distantia.ca/)
// +     improved by: davook
// +     improved by: Brett Zamir (http://brett-zamir.me)
// +     input by: Jay Klehr
// +     improved by: Brett Zamir (http://brett-zamir.me)
// +     input by: Amir Habibi (http://www.residence-mixte.com/)
// +     bugfix by: Brett Zamir (http://brett-zamir.me)
// *     example 1: number_format(1234.56);
// *     returns 1: '1,235'
// *     example 2: number_format(1234.56, 2, ',', ' ');
// *     returns 2: '1 234,56'
// *     example 3: number_format(1234.5678, 2, '.', '');
// *     returns 3: '1234.57'
// *     example 4: number_format(67, 2, ',', '.');
// *     returns 4: '67,00'
// *     example 5: number_format(1000);
// *     returns 5: '1,000'
// *     example 6: number_format(67.311, 2);
// *     returns 6: '67.31'
// *     example 7: number_format(1000.55, 1);
// *     returns 7: '1,000.6'
// *     example 8: number_format(67000, 5, ',', '.');
// *     returns 8: '67.000,00000'
// *     example 9: number_format(0.9, 0);
// *     returns 9: '1'
// *     example 10: number_format('1.20', 2);
// *     returns 10: '1.20'
// *     example 11: number_format('1.20', 4);
// *     returns 11: '1.2000'
// *     example 12: number_format('1.2000', 3);
// *     returns 12: '1.200'
  • 0
    Это только одна правильная функция:> number_format (2030, 0, '.', '') <'2 030' Отлично! Спасибо
15

Patrick Desjardins ответ выглядит хорошо, но я предпочитаю, чтобы мой javascript был прост. Здесь функция, которую я только что написал, чтобы взять число и вернуть его в формате валюты (минус знак доллара)

// Format numbers to two decimals with commas
function formatDollar(num) {
    var p = num.toFixed(2).split(".");
    var chars = p[0].split("").reverse();
    var newstr = '';
    var count = 0;
    for (x in chars) {
        count++;
        if(count%3 == 1 && count != 1) {
            newstr = chars[x] + ',' + newstr;
        } else {
            newstr = chars[x] + newstr;
        }
    }
    return newstr + "." + p[1];
}
15

Существует встроенный function toFixed в javascript

var num = new Number(349);
document.write("$" + num.toFixed(2));
  • 0
    Этот ответ выглядит излишним. Ответ Crush уже намечен toFixed()
  • 3
    toFixed() является функцией объекта Number и не будет работать с var num если это String , поэтому мне помог дополнительный контекст.
14

Не видел этого. Это довольно лаконично и легко понять.

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)
)
  • 0
    Отличный фрагмент кода, спасибо. Однако будьте осторожны, так как он не будет работать в IE, поскольку параметры по умолчанию не поддерживаются, а «const» и «let» не поддерживаются в <IE11. И это исправить: + moneyFormat: function (price, sign) {+ if (! Sign) sign = '$'; + штук = parseFloat (цена). toFixed (2) .split ('') + var ii = штук. длина - 3
  • 0
    Не беспокойся @CharlieDalsass. Я бы порекомендовал использовать babel для компиляции до ES5 для производственного кода.
Показать ещё 2 комментария
14

Я предлагаю класс NumberFormat из API визуализации Google.

Вы можете сделать что-то вроде этого:

var formatter = new google.visualization.NumberFormat({
    prefix: '$',
    pattern: '#,###,###.##'
});

formatter.formatValue(1000000); // $ 1,000,000

Надеюсь, это поможет.

13

Это может быть немного поздно, но вот метод, который я только что обработал для коллеги, чтобы добавить функцию .toCurrencyString(), поддерживающую локали, ко всем номерам. Интернализация предназначена только для группировки чисел, а не знака валюты - если вы выставляете доллары, используйте "$" как указано, потому что $123 4567 в Японии или Китае такое же количество долларов США, что и $1,234,567 здесь, в США, Если вы выставляете евро/и т.д., Измените знак валюты с "$".

Объявляйте это в любом месте своего HEAD или там, где это необходимо, непосредственно перед его использованием:

  Number.prototype.toCurrencyString = function(prefix, suffix) {
    if (typeof prefix === 'undefined') { prefix = '$'; }
    if (typeof suffix === 'undefined') { suffix = ''; }
    var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
    return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
  }

Тогда все готово! Используйте (number).toCurrencyString() где угодно, чтобы вывести номер в качестве валюты.

var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
13

Основная часть - вставка тысяч разделителей, что можно сделать следующим образом:

<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)));">
  • 0
    Я получаю неправильный вывод номера при вводе отрицательных значений в ins1000Sep ().
13
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.

  • 0
    Маленький и простой. Спасибо.
  • 0
    просто, но без запятой за 1000
10

Я нашел это от: 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€ 
  • 0
    $('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) ); - показать 1.000,00 E
10

Вот некоторые решения: все передают набор тестов, набор тестов и контрольный тест, если вы хотите скопировать и вставить для тестирования, попробуйте This Gist.

Метод 0 (RegExp)

База на https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-dollars-currency-string-in-javascript, но исправить, если нет десятичной точки.

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');
        a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
        return a.join('.');
    }
}

Способ 1

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.'),
            // skip the '-' sign
            head = Number(this < 0);

        // skip the digits that before the first thousands separator 
        head += (a[0].length - head) % 3 || 3;

        a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
        return a.join('.');
    };
}

Способ 2 (разделение на массив)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');

        a[0] = a[0]
            .split('').reverse().join('')
            .replace(/\d{3}(?=\d)/g, '$&,')
            .split('').reverse().join('');

        return a.join('.');
    };
}

Способ 3 (цикл)

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('');
        a.push('.');

        var i = a.indexOf('.') - 3;
        while (i > 0 && a[i-1] !== '-') {
            a.splice(i, 0, ',');
            i -= 3;
        }

        a.pop();
        return a.join('');
    };
}

Пример использования

console.log('======== Demo ========')
console.log(
    (1234567).format(0),
    (1234.56).format(2),
    (-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
    n = (n * 10) + (i % 10)/100;
    console.log(n.format(2), (-n).format(2));
}

Разделитель

Если мы хотим использовать разделитель разделителей тысяч или десятичный разделитель, используйте replace():

123456.78.format(2).replace(',', ' ').replace('.', ' ');

Комплект тестирования

function assertEqual(a, b) {
    if (a !== b) {
        throw a + ' !== ' + b;
    }
}

function test(format_function) {
    console.log(format_function);
    assertEqual('NaN', format_function.call(NaN, 0))
    assertEqual('Infinity', format_function.call(Infinity, 0))
    assertEqual('-Infinity', format_function.call(-Infinity, 0))

    assertEqual('0', format_function.call(0, 0))
    assertEqual('0.00', format_function.call(0, 2))
    assertEqual('1', format_function.call(1, 0))
    assertEqual('-1', format_function.call(-1, 0))
    // decimal padding
    assertEqual('1.00', format_function.call(1, 2))
    assertEqual('-1.00', format_function.call(-1, 2))
    // decimal rounding
    assertEqual('0.12', format_function.call(0.123456, 2))
    assertEqual('0.1235', format_function.call(0.123456, 4))
    assertEqual('-0.12', format_function.call(-0.123456, 2))
    assertEqual('-0.1235', format_function.call(-0.123456, 4))
    // thousands separator
    assertEqual('1,234', format_function.call(1234.123456, 0))
    assertEqual('12,345', format_function.call(12345.123456, 0))
    assertEqual('123,456', format_function.call(123456.123456, 0))
    assertEqual('1,234,567', format_function.call(1234567.123456, 0))
    assertEqual('12,345,678', format_function.call(12345678.123456, 0))
    assertEqual('123,456,789', format_function.call(123456789.123456, 0))
    assertEqual('-1,234', format_function.call(-1234.123456, 0))
    assertEqual('-12,345', format_function.call(-12345.123456, 0))
    assertEqual('-123,456', format_function.call(-123456.123456, 0))
    assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
    assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
    assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
    // thousands separator and decimal
    assertEqual('1,234.12', format_function.call(1234.123456, 2))
    assertEqual('12,345.12', format_function.call(12345.123456, 2))
    assertEqual('123,456.12', format_function.call(123456.123456, 2))
    assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
    assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
    assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
    assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
    assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
    assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
    assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
    assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
    assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}

console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);

Benchmark

function benchmark(f) {
    var start = new Date().getTime();
    f();
    return new Date().getTime() - start;
}

function benchmark_format(f) {
    console.log(f);
    time = benchmark(function () {
        for (var i = 0; i < 100000; i++) {
            f.call(123456789, 0);
            f.call(123456789, 2);
        }
    });
    console.log(time.format(0) + 'ms');
}

// if not using async, browser will stop responding while running.
// this will create a new thread to benchmark
async = [];
function next() {
    setTimeout(function () {
        f = async.shift();
        f && f();
        next();
    }, 10);
}

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
  • 0
    Улучшено по сравнению с вашим методом 2. измените с var a = this.toFixed (precision) .split ('.') На var multiplier = Math.pow (10, precision + 1), wholeNumber = Math.floor (this * множитель) ; var a = Math.round (wholeNumber / 10) * 10 / множитель; if (String (a) .indexOf ('.') <1) {a + = '.00'; } a = String (a) .split ('.'), не используйте toFixed, потому что он глючит.
  • 0
    console.log (parseFloat ( '4,835') toFixed (2).); > 4.83 console.log (parseFloat ('54 .835 '). ToFixed (2)); > 54.84 console.log (parseFloat ('454.835'). ToFixed (2)); > 454.83 console.log (parseFloat ('8454.835'). ToFixed (2)); > 8454.83 все эти десятичные значения должны быть .84, а не .83
10

Как обычно, существует несколько способов сделать одно и то же, но я бы избегал использования Number.prototype.toLocaleString, так как он может возвращать разные значения на основе пользовательских настроек.

Я также не рекомендую распространять прототипы собственных прототипов Number.prototype - это плохая практика, поскольку это может вызвать конфликты с кодом других людей (например, библиотеки/фреймворки/плагины) и может быть несовместимо с будущими реализациями JavaScript/версии.

Я считаю, что регулярные выражения - лучший подход к проблеме, вот моя реализация:

/**
 * Converts number into currency format
 * @param {number} number   Number that should be converted.
 * @param {string} [decimalSeparator]    Decimal separator, defaults to '.'.
 * @param {string} [thousandsSeparator]    Thousands separator, defaults to ','.
 * @param {int} [nDecimalDigits]    Number of decimal digits, defaults to `2`.
 * @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
 */
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
    //default values
    decimalSeparator = decimalSeparator || '.';
    thousandsSeparator = thousandsSeparator || ',';
    nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;

    var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
        parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]

    if(parts){ //number >= 1000 || number <= -1000
        return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
    }else{
        return fixed.replace('.', decimalSeparator);
    }
}

отредактировано в 2010/08/30: добавлена ​​опция для установки числа десятичных цифр. отредактированный в 2011/08/23: добавлена ​​возможность установить число десятичных цифр в ноль.

  • 0
    Смысл toLocaleString в том, что он настраивается с настройками пользователя.
9

Простая опция для правильного размещения в запятой, обращая сначала строку и основное регулярное выражение.

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();
};
8

Пример Патрика Дежардинса (ex Daok) хорошо работал у меня. Я пошлю к coffeescript, если кто-то заинтересован.

Number.prototype.toMoney = (decimals = 2, decimal_separator = ".", thousands_separator = ",") ->
    n = this
    c = if isNaN(decimals) then 2 else Math.abs decimals
    sign = if n < 0 then "-" else ""
    i = parseInt(n = Math.abs(n).toFixed(c)) + ''
    j = if (j = i.length) > 3 then j % 3 else 0
    x = if j then i.substr(0, j) + thousands_separator else ''
    y = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_separator)
    z = if c then decimal_separator + Math.abs(n - i).toFixed(c).slice(2) else ''
    sign + x + y + z
7

Кодовая база YUI использует следующее форматирование:

format: function(nData, oConfig) {
    oConfig = oConfig || {};

    if(!YAHOO.lang.isNumber(nData)) {
        nData *= 1;
    }

    if(YAHOO.lang.isNumber(nData)) {
        var sOutput = nData + "";
        var sDecimalSeparator = (oConfig.decimalSeparator) ? oConfig.decimalSeparator : ".";
        var nDotIndex;

        // Manage decimals
        if(YAHOO.lang.isNumber(oConfig.decimalPlaces)) {
            // Round to the correct decimal place
            var nDecimalPlaces = oConfig.decimalPlaces;
            var nDecimal = Math.pow(10, nDecimalPlaces);
            sOutput = Math.round(nData*nDecimal)/nDecimal + "";
            nDotIndex = sOutput.lastIndexOf(".");

            if(nDecimalPlaces > 0) {
                // Add the decimal separator
                if(nDotIndex < 0) {
                    sOutput += sDecimalSeparator;
                    nDotIndex = sOutput.length-1;
                }
                // Replace the "."
                else if(sDecimalSeparator !== "."){
                    sOutput = sOutput.replace(".",sDecimalSeparator);
                }
                // Add missing zeros
                while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
                    sOutput += "0";
                }
            }
        }

        // Add the thousands separator
        if(oConfig.thousandsSeparator) {
            var sThousandsSeparator = oConfig.thousandsSeparator;
            nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
            nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
            var sNewOutput = sOutput.substring(nDotIndex);
            var nCount = -1;
            for (var i=nDotIndex; i>0; i--) {
                nCount++;
                if ((nCount%3 === 0) && (i !== nDotIndex)) {
                    sNewOutput = sThousandsSeparator + sNewOutput;
                }
                sNewOutput = sOutput.charAt(i-1) + sNewOutput;
            }
            sOutput = sNewOutput;
        }

        // Prepend prefix
        sOutput = (oConfig.prefix) ? oConfig.prefix + sOutput : sOutput;

        // Append suffix
        sOutput = (oConfig.suffix) ? sOutput + oConfig.suffix : sOutput;

        return sOutput;
    }
    // Still not a Number, just return unaltered
    else {
        return nData;
    }
}

ему понадобится редактирование, поскольку библиотека YUI будет настраиваться, например, заменить oConfig.decimalSeparator на "."

  • 4
    Слишком долго, и я должен был бы включить YUI
  • 4
    Моей первой реакцией было "LOL - слишком долго, YUI отстой" ... но после пересмотра, это не плохой код, он просто очень ... завершен. Он проверяет, является ли arg на самом деле числом (не сделано другими авторами, и единственной частью, которая требует библиотеки YUI). Это делает округление (не сделано всеми плакатами). Он имеет настраиваемый разделитель, префикс и суффикс. Наконец, код комментируется и не использует регулярных выражений и хитрых однострочников. Итак ... я даю вам +1, чтобы компенсировать другим -1 ... этот код неплохой - его можно адаптировать, даже если не использовать YUI.
Показать ещё 1 комментарий
6

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;
        }
6

@tggagne верен. Мое решение ниже не хорошо из-за округления поплавка. И функции toLocaleString не хватает поддержки браузера. Я оставлю ниже комментарии для архивных целей того, что НЕ делать.:)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString#Browser_Compatibility

(старое решение) Вместо этого используйте решение Патрика Дежардинса.

Это краткое решение, использующее toLocaleString(), которое поддерживается с версии Javascript версии 1.0. Этот пример обозначает валюту в долларах США, но ее можно переключить на фунты, используя "GBP" вместо "USD".

var formatMoney = function (value) {
    // Convert the value to a floating point number in case it arrives as a string.
    var numeric = parseFloat(value);
    // Specify the local currency.
    return numeric.toLocaleString('USD', { style: 'currency', currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

Подробнее см. https://marcoscaceres.github.io/jsi18n/#localize_currency.

  • 0
    Не согласовано во всех браузерах: /
  • 0
    Спасибо за хедз-ап @godmode. В каких браузерах вы видели проблемы?
Показать ещё 3 комментария
5

Вы никогда не должны жестко кодировать свое решение, потому что это вызовет проблемы с обслуживанием, поскольку вы добавите больше локалей. И вы всегда должны использовать инструменты интернационализации для этой проблемы, потому что сложность форматирования чисел очень высока, так как вы добавляете все больше и больше локалей. Просто подумайте о том, как отформатировать ту же сумму, но вместо этого используйте арабские цифры? Или отформатировать ту же сумму на немецком языке? они используют разные символы для разделителя тысяч разделителей и фракций.

Что касается инструмента интернационализации, я использую l10ns (http://l10ns.org).

Вы просто пишете получатель для вашей локализованной строки.

var l = requireLocalizations('en-US');
var string = l('CURRENCY_AMOUNT', {
  price: {
    code: 'USD', //ISO currency code
    amount: 2500
  }
});

console.log(string) // Outputs '$ 2,500.00'

И определите свое сообщение возврата в своем инструменте интерфейса перевода.

{price, number, ¤ #,##0.00}

Третий приведенный выше аргумент называется десятичным паттерном. И он позволяет вам определить практически любой желаемый формат (мы используем decimal pattern, потому что вам нужно пространство между символом и суммой). Но для валюты, пожалуйста, используйте определенный десятичный шаблон по умолчанию, определенный CLDR. CLDR - это хранилище данных, которое используют многие организации, такие как Google, IBM, Yahoo и т.д. Для получения данных локализации. И одна из данных локализации, которую мы можем получить, заключается в форматировании суммы валюты. Их по умолчанию decimal pattern для английского языка ¤#,##0.00. И мы можем использовать этот шаблон, просто введя следующий текст в интерфейс трансляции.

{price, currency, local, symbol}

Для получения дополнительной информации ознакомьтесь с документацией .

5

Функция обработки валютного выпуска, включая негативы.

Результат:
$ 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();
}
5

http://code.google.com/p/javascript-number-formatter/:

  • Короткий, быстрый, гибкий, но автономный. Только 75 строк, включая информацию о лицензии MIT, пустые строки и комментарии.
  • Принять стандартное форматирование номера, например #, ## 0.00 или с отрицанием -000. ####.
  • Примите любой формат страны, например # ## 0,00, #, ###. ##, # '###. ## или любой тип символа без нумерации.
  • Принять любые цифры группировки цифр. #, ##, # 0.000 или #, ### 0. ## являются действительными.
  • Принять любое форматирование с избыточным/безумным подтверждением. ##, ###, ##. # или 0 #, # 00 #. ### 0 # все ОК.
  • Автоматическое округление номеров.
  • Простой интерфейс, просто укажите маску и значение, подобное этому: format ( "0.0000", 3.141592)

ОБНОВЛЕНИЕ Это мои домашние утилиты 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;
}
  • 0
    это просто скопировано из поиска Google. Проект не обновлялся с 2011 года
  • 0
    @ LukePage Может быть, это достаточно мачо? Кто знает...
4

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat Пример: использование локалей

В этом примере показаны некоторые варианты форматов локализованных номеров. Чтобы получить формат языка, используемого в пользовательском интерфейсе вашего приложения, обязательно укажите этот язык (и, возможно, некоторые резервные языки), используя аргумент locales:

var number = 123456.789;

//Немецкий использует запятую как десятичный разделитель и период для тысяч console.log(новый Intl.NumberFormat('de-DE'). format (number));//→ 123.456,789

//Арабский язык в большинстве стран арабского языка использует реальные арабские цифры console.log(новый Intl.NumberFormat('ar-EG'). format (number));//→ 123456. 789

//В Индии используются тысячи /lakh/crore separators console.log(new Intl.NumberFormat( 'ен-IN') формат (номер));.

4

Вам следует использовать инструмент интернационализации для решения этой проблемы, потому что, если вам это не нужно, вам нужно жестко закодировать много специфического кода, а количество перестановок бесконечно. Я использую l10ns. С L10ns вы можете просто определить свою строку сообщения как сумму валюты:

{price, currency, local, symbol}

Скомпилируйте сообщение:

$ l10ns compile

И попросите его и используйте его:

var l = requireLocalizations('en-US');
var carPrice = l('PRIZES__CAR_PRICE', { price: {
  code: 'USD',
  amount: 349
}});
// use carPrice...

PS. Не забывайте, что английский использует скобки ($ #, ## 0.00) для отрицательных сумм.

4

Intl.NumberFormat

var number = 3500;
alert(new Intl.NumberFormat().format(number));
// → "3,500" if in US English locale

или phpjs.com/functions/number_format

  • 0
    Запрашиваемая JS решение!
4

Код от 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"
4

Вот короткая и лучшая конвертация чисел в формат валюты:

function toCurrency(amount){
    return amount.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}

// usage: toCurrency(3939920.3030);

Ура! Anunay

  • 1
    toCurrency('123456.7890') возвращает 123,456.7,890 . ИМХО, не должно быть никаких запятых в десятичных разрядах. Кроме того, выглядит хорошо!
4

Этот ответ отвечает следующим критериям:

  • Не зависит от внешней зависимости.
  • Поддерживает локализацию.
  • Имеет ли тесты/доказательства.
  • Использует простые и лучшие методы кодирования (без сложных регулярных выражений, использует стандартные шаблоны кодирования).

Этот код построен на концепциях из других ответов. Эта скорость выполнения должна быть среди лучших, размещенных здесь, если это вызывает беспокойство.

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 + "\"");
    }
}
3

toLocaleString хорош, но не работает во всех браузерах. Обычно я использую currencyFormatter.js(https://osrec.github.io/currencyFormatter.js/). Он довольно легкий и содержит все определения валюты и локали прямо из коробки. Это также хорошо при форматировании необычно отформатированных валют, таких как INR (число групп в лаках и крорах и т.д.). Также нет зависимостей!

OSREC.CurrencyFormatter.format(2534234, { currency: 'INR' }); // Returns ₹ 25,34,234.00

OSREC.CurrencyFormatter.format(2534234, { currency: 'EUR' }); // Returns 2.534.234,00 €

OSREC.CurrencyFormatter.format(2534234, { currency: 'EUR', locale: 'fr' }); // Returns 2 534 234,00 €

3

Вот реализация 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) : '');
});
3

В JavaScript нет эквивалента "formatNumber". Вы можете написать его самостоятельно или найти библиотеку, которая уже делает это.

3

Способ Quiker с регулярным выражением?

Number.prototype.toMonetaryString=function(){var n=this.toFixed(2),m;
// var=this.toFixed(2).replace(/\./,','); for comma separator
// with a space for thousands separator
  while ((m=n.replace(/(\d)(\d\d\d)\b/g,'$1 $2'))!=n) n=m; 
  return m;
}
String.prototype.fromMonetaryToNumber=function(s){
  return this.replace(/[^\d-]+/g,'')/100;
}   
3

Это может сработать:

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));
}

Нет циклов, не существует регулярных выражений, нет массивов, нет экзотических условностей.

3

Минималистский подход, который отвечает только оригинальным требованиям:

function formatMoney(n) {
    return "$ " + (Math.round(n * 100) / 100).toLocaleString();
}

@Даниэль Маглиола: Вы правы, вышеупомянутое было поспешным, неполным воплощением. Здесь исправленная реализация:

function formatMoney(n) {
    return "$ " + n.toLocaleString().split(".")[0] + "."
        + n.toFixed(2).split(".")[1];
}
  • 1
    Извините, нет. Это удалит лишние десятичные разряды, но не установит 2 десятичных разряда. «25» будет «$ 25» с вашим кодом, а не «$ 25,00»
  • 0
    Исправлена реализация выше.
Показать ещё 3 комментария
2

Я хотел, чтобы ванильное 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");
2

Мне было трудно найти простую библиотеку для работы с датой и валютой, поэтому я создал мою: https://github.com/dericeira/slimFormatter.js

Простое:

var number = slimFormatter.currency(2000.54);
2

у многих ответов были полезные идеи, но ни один из них не соответствовал моим потребностям. Поэтому я использовал все идеи и построил этот пример:

function Format_Numb( fmt){
    var decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
    if(typeof decSgn==="undefined") decSgn = ".";
    if(typeof kommaSgn==="undefined") kommaSgn= ",";

    var s3digits=/(\d{1,3}(?=(\d{3})+(?=[.]|$))|(?:[.]\d*))/g;
    var dflt_nk="00000000".substring(0,decimals);

    //--------------------------------
    // handler for pattern: "%m"
    var _f_money= function( v_in){
                var v=v_in.toFixed(decimals);
                var add_nk=",00";
                var arr=    v.split(".");
                return     arr[0].toString().replace(s3digits, function ($0) {
                                    return ($0.charAt(0)==".")
                                        ? ((add_nk=""),(kommaSgn + $0.substring(1)))
                                        : ($0 + decSgn);
                        })
                        + (    (decimals > 0)
                                ?    (    kommaSgn
                                        + (
                                            (arr.length > 1)
                                            ? arr[1]
                                            : dflt_nk
                                        )
                                    )
                                :    ""                    
                        );
    }

    // handler for pattern: "%<len>[.<prec>]f"
    var _f_flt= function( v_in,l,prec){
        var v=(typeof prec !== "undefined") ? v_in.toFixed(prec):v_in;
        return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
                ?(Array(l+1).join(" ") + v)
                :v;
    }

    // handler for pattern: "%<len>x"
    var _f_hex= function( v_in,l,flUpper){
        var v=    Math.round(v_in).toString(16);
        if(flUpper)    v=v.toUpperCase();
        return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
                ?(Array(l+1).join("0") + v)
                :v;        
    }

    //...can be extended..., just add the function, f.e.:    var _f_octal= function( v_in,...){
    //--------------------------------

    if( typeof(fmt)!=="undefined"){
        //...can be extended..., just add the char,f.e."O":    MFX -> MFXO
        var rpatt=/(?:%([^%"MFX]*)([MFX]))|(?:"([^"]*)")|("|%%)/gi;
        var _qu=    "\"";
        var _mask_qu=    "\\\"";
        var str=    fmt.toString().replace( rpatt,function($0,$1,$2,$3,$4){
                                var f;
                                if(typeof $1 !== "undefined"){
                                    switch($2.toUpperCase()){
                                        case "M":    f= "_f_money(v)";    break;
                                        case "F":    var    n_dig0,n_dig1;
                                                var    re_flt=/^(?:(\d))*(?:[.](\d))*$/;
                                                $1.replace(re_flt,function($0,$1,$2){
                                                    n_dig0=$1;
                                                    n_dig1=$2;
                                                });
                                                f= "_f_flt(v," + n_dig0 + "," + n_dig1 + ")";    break;
                                        case "X":    var    n_dig="undefined";
                                                var    re_flt=/^(\d*)$/;
                                                $1.replace(re_flt,function($0){
                                                    if($0!="")n_dig=$0;
                                                });
                                                f= "_f_hex(v," + n_dig + "," + ($2=="X") + ")";    break;
                                        //...can be extended..., f.e.:    case "O":
                                    }
                                    return "\"+"+f+"+\"";
                                } else if(typeof $3 !== "undefined"){
                                    return _mask_qu + $3 + _mask_qu;
                                } else {
                                    return ($4==_qu)?_mask_qu:$4.charAt(0);
                                }
                            });
        var cmd=        "return function(v){"
                +        "if(typeof v === \"undefined\")return \"\";"    //null returned as empty string
                +        "if(!v.toFixed)return v.toString();"        //not numb returned as string
                +        "return \"" + str + "\";"
                +    "}";

        //...can be extended..., just add the function name in the 2 places:
        return new Function( "_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex);
    }
}

Во-первых, мне понадобилось C-style format-string-definition, которое должно быть гибким, но очень простым в использовании, и я определил его следующим образом; шаблоны:

%[<len>][.<prec>]f        float, example "%f", "%8.2d", "%.3f"
%m                        money
%[<len>]x                 hexadecimal lower case, example "%x", "%8x"
%[<len>]X                 hexadecimal upper case, example "%X", "%8X"

потому что нет необходимости форматировать другие, а затем для меня для евро, я реализовал только "% m". Но это легко расширить... Как и в C, строка формата представляет собой строку, содержащую шаблоны, F.E. для евро: "% m €" (возвращает строки типа "8.129,33 €" )

Помимо гибкости мне понадобилось очень быстрое решение для обработки таблиц. Это означает, что при обработке тысяч ячеек обработка строки формата не должна выполняться более одного раза. Вызов типа "format (value, fmt)" не подходит для меня, но это должно быть разделено на два этапа:

// var formatter = Format_Numb( "%m €");  
//simple example for Euro...

//   but we use a complex example: 

var formatter = Format_Numb("a%%%3mxx \"zz\"%8.2f°\"  >0x%8X<");

// formatter is now a function, which can be used more than once (this is an example, that can be tested:) 

var v1= formatter( 1897654.8198344); 

var v2= formatter( 4.2); 

... (and thousands of rows)

Кроме того, для производительности, _f_money закрывает regexp;

В-третьих, вызов типа "format (value, fmt)" неприемлем, потому что: Хотя должно быть возможно отформатировать различные коллекции объектов (например, ячейки столбца) с разными масками, я не хочу иметь что-то, чтобы обрабатывать строки форматирования в точке обработки. На данный момент я хочу использовать только USE форматирование, например,

для (ячейка var в ячейках) {do_something (cell.col.formatter( cell.value)); }

Какой формат - возможно, он определен в ini, в xml для каждого столбца или где-то еще..., но анализ и настройка форматов или работа с internationalizaton обрабатывается полностью другим место, и там я хочу назначить форматтер коллекции, не думая о проблемах с производительностью:

col.formatter = Format_Numb (_getFormatForColumn (...));

В-четвертых, мне понадобилось "толерантное" решение, поэтому прохождение f.e. строка вместо числа должна возвращать просто строку, но "null" должна возвращать пустую строку.

(Также форматирование "% 4.2f" не должно вырезать что-то, если значение слишком велико.)

И последнее, но не менее важное - оно должно быть легко читаемым и легко расширяемым, без каких-либо эффектов в производительности... Например, если кому-то нужны "восьмеричные значения", обратитесь к строкам с "... может быть расширен..." - я думаю, что это должна быть очень простая задача.

Мое основное внимание было сосредоточено на производительности. Каждая "процедура обработки" (fe_f_money) может быть инкапсулирована оптимизирована или обменена другими идеями в этом или другом потоке без изменения "подпрограмм подготовки" (анализ строк формата и создание функций), которые должны обрабатываться только один раз и в этом смысл не так критичен по производительности, как призывы к конверсии тысяч чисел.

Для всех, кто предпочитает методы чисел:

Number.prototype.format_euro=( function(formatter){
    return function(){ return formatter(this); }})
    (Format_Numb( "%m €"));

var v_euro= (8192.3282).format_euro(); //results: 8.192,33 €

Number.prototype.format_hex= (function(formatter){
    return function(){ return formatter(this); }})
    (Format_Numb( "%4x"));

var v_hex= (4.3282).format_hex();

Хотя я тестировал что-то, в коде может быть много ошибок. Так что это не готовый модуль, а просто идея и отправная точка для не-js-экспертов, подобных мне. Код содержит много и мало измененных идей из множества сообщений stackoverflow; извините, я не могу сослаться на все из них, но спасибо всем экспертам.

2

Мне нравится кратчайший ответ VisionN, за исключением случаев, когда мне нужно изменить его на число без десятичной точки ($ 123 вместо $123.00), это не сработает, поэтому вместо быстрой копии/вставки мне нужно расшифровать тайный синтаксис JavaScript регулярное выражение.

Вот оригинальное решение

n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');

Я сделаю это немного дольше:

var re = /\d(?=(\d{3})+\.)/g;
var subst = '$&,';
n.toFixed(2).replace(re, subst);

Re часть здесь (часть поиска в замене строки) означает

  • Найти все цифры (\d)
  • Далее следуют (?=...) (lookahead)
  • Одна или несколько групп (... )+
  • Всего ровно 3 цифры (\d{3})
  • Окончание с точкой (\.)
  • Сделайте это для всех вхождений (g)

Subst здесь означает

  • Каждый раз, когда есть совпадение, замените его на себя ($&), за которым следует запятая.

Поскольку мы используем string.replace, все остальные тексты в строке остаются теми же, и только найденные цифры (те, за которыми следуют 3,6,9 и т.д. другие цифры) получают дополнительную запятую.

Итак, в количестве 1234567.89 цифры 1 и 4 соответствуют условию ( 1 23 4 567.89) и заменены на " 1," и " 4,", что приводит к 1 234 567,89.

Если нам вообще не нужна десятичная точка в долларовой сумме (т.е. $123 вместо $123.00), мы можем изменить регулярное выражение следующим образом:

var re2 = /\d(?=(\d{3})+$)/g;

Он полагается на конец строки ($) вместо точки (\.), и окончательное выражение будет (обратите внимание также на toFixed(0)):

n.toFixed(0).replace(/\d(?=(\d{3})+$)/g, '$&,');

Это выражение даст

1234567.89 -> 1,234,567

Также вместо конца строки ($) в регулярном выражении вы также можете выбрать границу слова (\b).

Мои извинения заранее, если я неверно истолковал любую часть обработки регулярных выражений.

2

Потому что почему бы не добавить еще один ответ. Я основывал это на ответе 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

Просто для удовольствия.

2

Coffeescript для Patrick популярный ответ выше:

Number::formatMoney = (decimalPlaces, decimalChar, thousandsChar) ->  
  n = this  
  c = decimalPlaces  
  d = decimalChar  
  t = thousandsChar  
  c = (if isNaN(c = Math.abs(c)) then 2 else c)  
  d = (if d is undefined then "." else d)  
  t = (if t is undefined then "," else t)  
  s = (if n < 0 then "-" else "")  
  i = parseInt(n = Math.abs(+n or 0).toFixed(c)) + ""  
  j = (if (j = i.length) > 3 then j % 3 else 0)  
  s + (if j then i.substr(0, j) + t else "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (if c then d + Math.abs(n - i).toFixed(c).slice(2) else "")  
2
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
1

Здесь простой форматирующий элемент в ваниле 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;

}
1

Я хочу внести свой вклад:

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>
1

Уже есть хорошие ответы. Здесь простая попытка для удовольствия:

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)
)
1

Мне нравится просто:

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("");
}
1
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

0

Number(value)
        .toFixed(2)
        .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
0

Поскольку каждая проблема имеет однострочное решение:

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
0

Здесь моя...

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;
}
-1

Вот быстрый способ с помощью regexp и замены.

function formatCurrency( number, dp, ts ) {
  var num = parseFloat( number ); //convert to float
  var pw; //for IE
  dp = parseInt( dp, 10 ); //decimal point
  dp = isNaN( dp ) ? 2 : dp; //default 2 decimal point
  ts = ts || ','; //thousands separator

  return num != number ? 
    false : //return false for NaN
    ( ( 0.9 ).toFixed( 0 ) == '1' ? //for cater IE toFixed bug
        num.toFixed( dp ) : //format to fix n decimal point with round up
        ( Math.round( num * ( pw = Math.pow( 10, dp ) || 1 ) ) / pw ).toFixed( dp ) //for fix ie toFixed bug on round up value like 0.9 in toFixed
    ).replace( /^(-?\d{1,3})((\d{3})*)(\.\d+)?$/, function( all, first, subsequence, dmp, dec ) { //separate string into different parts
      return ( first || '' ) + subsequence.replace( /(\d{3})/g, ts + '$1' ) + ( dec || '' ); //add thousands seperator and re-join all parts
    } );
}
  • 2
    пожалуйста, приведите пример использования этой функции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню