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

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

"$ 2,500.00"

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

1606
задан 12 revs, 8 users 31% 26 May 2019 в 04:14
поделиться

61 ответ

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

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

26
ответ дан Daniel Magliola 26 May 2019 в 04:14
поделиться

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(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;

return sign +
	(j ? i.substr(0, j) + thouSep : "") +
	i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "$1" + thouSep) +
	(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}

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

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

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

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

(123456789.12345).formatMoney(2);

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

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

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

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

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

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

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

    return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
  } catch (e) {
    console.log(e)
  }
};
document.getElementById("b").addEventListener("click", event => {
  document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>
1678
ответ дан 11 revs, 10 users 43% 26 May 2019 в 04:14
поделиться

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
ответ дан jacob 26 May 2019 в 04:14
поделиться

Вот самый короткий и лучший способ конвертировать числа в формат валюты:

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

// usage: toCurrency(3939920.3030);

Ура! Anunay

4
ответ дан Anunay 26 May 2019 в 04:14
поделиться

Intl.NumberFormat

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

или phpjs.com/functions/number_format

5
ответ дан iBet7o 26 May 2019 в 04:14
поделиться

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

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

var number = 123456.789;

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

// В большинстве говорящих на арабском языке арабских языков используются настоящие арабские цифры console.log (new Intl.NumberFormat ('ar-EG'). Format (number)); // → ١٢٣٤٥٦ ٫ ٧٨٩

// Индия использует разделители тысяч / лакх / крор console.log (новый Intl.NumberFormat ('en-IN'). Format (number));

4
ответ дан Mohamed.Abdo 26 May 2019 в 04:14
поделиться

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

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];
}
3
ответ дан 4 revs 26 May 2019 в 04:14
поделиться

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

3
ответ дан Diodeus - James MacFarlane 26 May 2019 в 04:14
поделиться

Потому что, почему бы не добавить еще один ответ. Я основал это на ответ от 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
ответ дан kalisjoshua 26 May 2019 в 04:14
поделиться

Код от 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
ответ дан Tom 26 May 2019 в 04:14
поделиться

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

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
ответ дан 2 revs 26 May 2019 в 04:14
поделиться

Мне нравится самый короткий ответ от VisionN, за исключением случаев, когда мне нужно изменить его для числа без десятичной точки (123 доллара вместо 123,00 долларов США), он не работает, поэтому вместо быстрого копирования / вставки мне нужно расшифровать тайный синтаксис JavaScript регулярное выражение. [1 131]

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

n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '[110]amp;,');

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

var re = /\d(?=(\d{3})+\.)/g;
var subst = '[111]amp;,';
n.toFixed(2).replace(re, subst);

Re part here (поиск части в строке заменяет) означает

  1. Найти все цифры (\d)
  2. Затем следует (?= ...) (взгляд вперед)
  3. Одна или несколько групп ( ... )+
  4. Ровно из 3 цифр (\d{3})
  5. Окончание с точкой (\.)
  6. Сделайте это для всех случаев (g)

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

  1. Каждый раз, когда есть совпадение, заменяйте его на себя ([1114]amp;), за которым следует запятая.

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

Таким образом, в числе 1234567,89 цифры 1 и 4 соответствуют условию ( 1 23 4 567,89) и заменяются на « 1, "и" 4, ", что привело к 1 234 567,89.

Если нам вообще не нужна десятичная точка в долларах (т. Е. 123 доллара вместо 123,00 долларов США), мы можем изменить регулярное выражение следующим образом:

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

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

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

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

1234567.89 -> 1,234,567

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

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

2
ответ дан mp31415 26 May 2019 в 04:14
поделиться
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

1
ответ дан 3 revs 26 May 2019 в 04:14
поделиться
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
2
ответ дан 2 revs 26 May 2019 в 04:14
поделиться

Более быстрый способ с помощью регулярных выражений?

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
ответ дан Julien de Prabère 26 May 2019 в 04:14
поделиться

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

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

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

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

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

См. https://marcoscaceres.github.io/jsi18n/#localize_currency для получения дополнительной информации.

6
ответ дан 2 revs 26 May 2019 в 04:14
поделиться

Вот реализация 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
ответ дан Kirk Bentley 26 May 2019 в 04:14
поделиться

Уже есть хорошие ответы. Вот простая попытка для развлечения:

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
ответ дан rab 26 May 2019 в 04:14
поделиться

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

Простая как это:

var number = slimFormatter.currency(2000.54);
2
ответ дан Daniel Campos 26 May 2019 в 04:14
поделиться

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

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

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

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 + "\"");
    }
}
4
ответ дан 4 revs 26 May 2019 в 04:14
поделиться

Я хотел ванильное решение 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
ответ дан Nicolas Giszpenc 26 May 2019 в 04:14
поделиться

Вот простой форматировщик в vanilla JS:

function numberFormatter (num) {
        console.log(num)
    var wholeAndDecimal = String(num.toFixed(2)).split(".");
    console.log(wholeAndDecimal)
    var reversedWholeNumber = Array.from(wholeAndDecimal[0]).reverse();
    var formattedOutput = [];

    reversedWholeNumber.forEach( (digit, index) => {
        formattedOutput.push(digit);
        if ((index + 1) % 3 === 0 && index < reversedWholeNumber.length - 1) {
            formattedOutput.push(",");
        }
    })

    formattedOutput = formattedOutput.reverse().join('') + "." + wholeAndDecimal[1];

    return formattedOutput;

}
1
ответ дан 2 revs 26 May 2019 в 04:14
поделиться

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 "")  
2
ответ дан DanielEli 26 May 2019 в 04:14
поделиться

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

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

(отрывок из его README)

24
ответ дан 2 revs, 2 users 62% 26 May 2019 в 04:14
поделиться

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

  • Короткий, быстрый, гибкий, но автономный. Всего 75 строк, включая информацию о лицензии MIT, пустые строки и комментарии.
  • Принять стандартное форматирование чисел, например #, ## 0,00 или с отрицанием -000. ####.
  • Примите любой формат страны, например # ## 0,00, #, ###. ##, # '###. ## или любой тип не нумерованного символа.
  • Принимайте любые цифры группировки цифр. #, ##, # 0.000 или #, ### 0. ## все действительны.
  • Примите любое избыточное / надежное форматирование. ##, ###, ##. # или 0 #, # 00 #. ### 0 # все в порядке.
  • Автоматическое округление чисел.
  • Простой интерфейс, просто поставьте маску и усилитель; значение как это: формат ("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;
}
5
ответ дан gavenkoa 26 May 2019 в 04:14
поделиться

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

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

будет производить строку "-$123.00".

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

114
ответ дан 3 revs, 3 users 37% 26 May 2019 в 04:14
поделиться

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

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"

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

72
ответ дан 2 revs, 2 users 91% 26 May 2019 в 04:14
поделиться

Вот мой ...

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
ответ дан mendezcode 26 May 2019 в 04:14
поделиться

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

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

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

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

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

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

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

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

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

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

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

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

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

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

//   but we use a complex example: 

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

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

var v1= formatter( 1897654.8198344); 

var v2= formatter( 4.2); 

... (and thousands of rows)

Также для производительности _f_money заключает в себе регулярное выражение;

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

для (var cell in cell) {do_something (cell.col.formatter (cell.value)); }

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

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

В-четвертых, я хотел «толерантное» решение , поэтому прохождение fe строка вместо числа должна возвращать просто строку, но «null» должна возвращать пустую строку.

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

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

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

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

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

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

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

var v_hex= (4.3282).format_hex();

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

2
ответ дан user2807653 26 May 2019 в 04:14
поделиться

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

(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

64
ответ дан Nick Grealy 26 May 2019 в 04:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: