Как форматировать числа как денежные строки

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

"$ 2,500.00"

Как лучше всего это сделать?


person Community    schedule 29.09.2008    source источник
comment
Желательно, не обязательно. Я только что опубликовал ответ, который, как мне кажется, основан на предложениях людей.   -  person Daniel Magliola    schedule 29.09.2008
comment
Пожалуйста, всем, кто будет читать это в будущем, не используйте float для хранения валюты. Вы потеряете точность и данные. Вы должны сохранить его как целое число центов (или пенсов и т. Д.), А затем преобразовать перед выводом.   -  person Philip Whitehouse    schedule 04.03.2012
comment
@PhilipWhitehouse, что может привести к потере данных с менее чем двумя десятичными знаками?   -  person Kyle    schedule 22.05.2012
comment
@ user1308743 Float не хранит десятичные разряды. Он хранит числа, используя значение, базу и смещение. 0,01 на самом деле не представляется. См .: en.wikipedia.org/wiki/Floating_point#Accuracy_problems.   -  person Philip Whitehouse    schedule 10.06.2012
comment
@ user1308743: Представьте, что вы представляете очень большое число (допустим, вы счастливчик, и это баланс вашего банковского счета). Вы действительно хотите потерять деньги из-за недостатка точности?   -  person ereOn    schedule 06.08.2012
comment
@PhilipWhitehouse прав: хранить деньги как поплавок - определенно плохая идея. Однако хранение денег в виде центов работает только тогда, когда вы имеете дело только с целыми центами, что недостаточно точно для многих операций. Недавно мы перешли на хранение валюты в виде «большого десятичного знака» с 7 знаками после запятой. Вы можете использовать метод Javascript toFixed (7) для имитации этого, хотя при необходимости он возвращает строку. Однако это означает, что вы можете работать со знакомыми форматами $ xx.xx, не конвертируясь обратно из центов.   -  person Ben Hull    schedule 16.05.2013
comment
Так почему никто не предложил следующее? (2500) .toLocaleString (en-GB, {style: currency, currency: GBP, minimumFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/   -  person Nick Grealy    schedule 25.09.2013
comment
@NickG Полагаю, из-за того, что поддержка устаревших браузеров довольно дрянная. Но в идеальном мире (где у всех есть современные браузеры) это было бы лучшим решением.   -  person Ben    schedule 19.08.2014
comment
вы можете использовать эту javascript-библиотеку Numeral.js для преобразования ваших чисел в доллары. (numeraljs.com) для справки.   -  person Aarthi    schedule 11.09.2014
comment
Не забудьте, что на английском языке в скобках ($#,##0.00) указываются отрицательные суммы валюты.   -  person einstein    schedule 26.10.2014
comment
@NickG Я был в восторге от вашего решения, но не работает в IPad, Android и IE7, работает только в Mozilla и Opera из того, что я проверял   -  person Testo Testini    schedule 06.02.2015
comment
@TestoTestini - спасибо, Mozilla задокументировала таблицу совместимости для браузеров developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/   -  person Nick Grealy    schedule 06.02.2015
comment
@TestoTestini (a) NickG См. Этот jsFiddle: jsfiddle.net/v7tws309   -  person cssyphus    schedule 07.02.2015
comment
@RoccoTheTaco: Не уверен, что вы говорите. Другой вопрос старше, имеет больше голосов, больше ответов и ответ с большим количеством голосов. (Субъективное) среднее качество ответов аналогично. Если честно, их лучше объединить.   -  person Bergi    schedule 08.05.2015
comment
Нет ничего плохого в том, чтобы быть универсальным, не так ли?   -  person Bergi    schedule 10.05.2015
comment
@PhilipWhitehouse Хотя хранить его как float нехорошо, я считаю, что можно отображать валюту в js как float. Пока вы не выполняете над ним вычисления, например, суммируете столбец и т. Д. Я сохраняю и обрабатываю значение в десятичном формате C # и просто отправляю его в js как float, где оно отображается. Если вы введете в консоль .1 или .61, он будет отображаться нормально, хотя 1.03– .42 - нет. Элементарный тест: для (var i = -200; i ‹= 200; ++ i) console.log (i / 100); Я также отправляю отредактированные числа с плавающей запятой обратно на свой веб-сервер, что должно быть в порядке: JSON.stringify (.1): 0.1.   -  person Curtis Yallop    schedule 08.06.2015
comment
Если вы читаете это в ›= 2017, это должно быть полезно: ссылка   -  person Amir    schedule 21.02.2017
comment
@Amir, это уже в моем ответе   -  person aross    schedule 05.07.2017
comment
@CurtisYallop, только если отображается стоимость без валюты, потому что english.stackexchange.com/a/11327/118419   -  person LogicDaemon    schedule 14.03.2019
comment
@NickGrealy Святое дерьмо. Чувак, я не знал этой функции. Я всегда писал свои кастомные функции. Cooooool. Спасибо   -  person Mike Aron    schedule 29.11.2020
comment
Спасибо, @MikeAron, в любое время. Поставьте этому +1, чтобы помочь другим - stackoverflow.com/a/18994850/782034   -  person Nick Grealy    schedule 29.11.2020
comment
Для конвертации INR используйте (4027775861.4) .toLocaleString ('en-IN', {maximumFractionDigits: 2, style: 'currency', currency: 'INR'}); // возврат - ›4,02,77,75,861,40   -  person Rajeev Jayaswal    schedule 17.12.2020
comment
@Philip Whitehouse: * потерять точность (не низкая точность). (Исправить может только модератор - можно поднять флаг модератора.)   -  person Peter Mortensen    schedule 01.05.2021


Ответы (67)


Intl.NumberFormat

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

// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',

  // These options are needed to round to whole numbers if that's what you want.
  //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
  //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
});

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

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

Вот список кодов валют.

Intl.NumberFormat против Number.prototype.toLocaleString

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

Кроме того, производительность обоих одинакова для одиночного элемента, но если вам нужно отформатировать много чисел, использование Intl.NumberFormat будет примерно в 70 раз быстрее. Поэтому обычно лучше использовать Intl.NumberFormat и создавать экземпляр только один раз при загрузке страницы. В любом случае, вот эквивалентное использование toLocaleString:

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

Некоторые примечания о поддержке браузером и Node.js

  • Поддержка браузера больше не является проблемой: 98% поддержки во всем мире, 99% в США и 99 +% в ЕС.
  • Существует прокладка для поддержки этого в ископаемых браузерах (например, Internet Explorer 8), если вам действительно нужно
  • Node.js до v13 поддерживает только en-US из коробки. Одно из решений - установить full-icu, см. здесь для получения дополнительной информации.
  • Дополнительную информацию см. На странице CanIUse.
person Community    schedule 26.04.2013
comment
Голосую за этот, потому что это глупо простой ответ, который работает изначально. - person Trasiva; 31.08.2016
comment
Совершенно уверен, что довольно большое количество браузеров теперь поддерживают это. За это следует проголосовать гораздо больше. - person flq; 24.12.2016
comment
Это отличный ответ, и у меня он работает с динамической стоимостью валюты, поэтому, если используется в Европе, она меняется на евро и показывает знак евро. Работает удовольствие! - person Sprose; 14.09.2017
comment
Отлично работает и в React Native! - person flyandi; 14.06.2018
comment
Это 2018 год, и это в основном поддерживается повсюду. Это должен быть правильный ответ. - person sarink; 27.09.2018
comment
Поддерживается еще в Internet Explorer 11 (IE 11), а также поддерживаются все основные браузеры. - person Matt Jensen; 07.02.2020
comment
есть ли способ отменить это, вернув 2500 долларов США к строке вроде 2500.00 - person RkuangDev; 26.08.2020
comment
@RkuangDev Конечно, но вам нужно знать используемый десятичный разделитель. Если это точка (самый простой сценарий), это будет работать: parseFloat('$2,345.67'.replace(/[^0-9.]/g, '')). Разумеется, остерегайтесь плавающих валютных курсов. - person aross; 26.08.2020
comment
Почему это не принятый ответ? Красиво работает! - person Olawale Oladiran; 13.11.2020
comment
Добавьте maximumFractionDigits: 0, если хотите получить ответ в форме $2,500. Так было бы: return (num).toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractionDigits: 0 }); - person Aljosha Novakovic; 25.03.2021
comment
@AljoshaNovakovic Правильно, это тоже уже в ответе :) - person aross; 25.03.2021
comment
ааа да не видел в комментариях. Хороший ответ! - person Aljosha Novakovic; 05.04.2021

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>

person Community    schedule 29.09.2008
comment
Если вы всегда хотите округлить до 5 и меньше 5, вы не можете полагаться на toFixed () из-за стандартных проблем, связанных с представлением чисел с плавающей запятой в двоичном формате. Например, попробуйте (1.005).toFixed(2). - person Ryan; 19.10.2010
comment
в первую очередь отличный, лаконичный код. однако, если вы американец, вам следует изменить значения по умолчанию для d и t на . и , соответственно, чтобы вам не приходилось указывать их каждый раз. Кроме того, я рекомендую изменить начало оператора return следующим образом: return s + '$' + [rest], иначе вы не получите знак доллара. - person Jason; 01.02.2011
comment
Спасибо, это здорово. Изменен для работы со строками, вводимыми пользователем (сначала преобразует строку в числа, если они вводят 1500 долларов). String.prototype.formatMoney = function (c, d, t) {var n_dirty = this, n = n_dirty.replace (/ [^ \ d.] / G, ''), c = isNaN (c = Math.abs ( в))? 2: c, d = d == undefined? . : d, t = t == undefined? ,: t, s = n ‹0? -:, i = parseInt (n = Math.abs (+ 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):); }; - person Zhenya; 20.08.2011
comment
Вы можете использовать «10» в качестве основания в parseInt. В противном случае для любого числа, начинающегося с «0», будет использоваться восьмеричная нумерация. - person sohtimsso1970; 15.11.2011
comment
Значение по умолчанию, равное 0, остается восьмеричным, но не рекомендуется. Но да, вы можете добавить это, если хотите. - person Patrick Desjardins; 15.11.2011
comment
Не уверен, почему люди считают этот код красивым. Это не поддается расшифровке. Вроде неплохо работает, но некрасиво. - person usr; 24.10.2012
comment
Копируется ли эта функция formatMoney из какого-нибудь миниатюрного кода JavaScript? А оригинал нельзя выложить? Что обозначают переменные c, d, i, j, n, s и t? Судя по количеству голосов и комментариев к этому сообщению, я могу предположить, что этот код был скопирован и вставлен на производственные веб-сайты повсюду ... Удачи в поддержании кода, если когда-нибудь в нем будет ошибка! - person zuallauz; 18.12.2012
comment
Это решение работает не очень хорошо. 1.155.formatMoney (2, '.', ',) ===' 1.16 ', но 2.155.formatMoney (2,'. ',', ') ===' 2.15 ' - person Nick Colgan; 21.12.2012
comment
поэзия? Больше похоже на безвестность. Это не кодовый гольф; используйте небольшое пустое пространство. Правильные имена var тоже не повредят. - person keithjgrant; 30.12.2012
comment
Не говоря уже о том, что d == undefined используется, а typeof(d) === 'undefined' должен быть на месте. - person trejder; 27.08.2013
comment
@trejder почему так? Если у вас есть глупые программисты, которые определяют undefined как переменную с содержимым, вам хорошо. Кстати, вам не нужно (и поэтому не следует) использовать круглые скобки для typeof. - person Micaël Félix; 25.09.2013
comment
@MykaEyl Прочтите об основах JS, прежде чем говорить что-то, что ... немного неправильно. Переменная с именем undefined определяется JS, а не какими-то глупыми программистами, и вам следует использовать круглые скобки для typeof, потому что без нее вы будете сравнивать ее с этой переменной с именем undefined. Я не излагаю здесь свои мысли, я просто скопировал то, что выражено во многих ответах SO и во многих источниках. Сейчас нет времени искать пример, но вы обязательно его найдете, если погуглите еще немного. - person trejder; 25.09.2013
comment
@trejder Скобки с typeof абсолютно не влияют на то, как конструкция анализирует эту форму - _ 1_ имеет тот же приоритет, что и унарный оператор. Также в предыдущем комментарии говорилось, что безопасно полагаться на то, что undefined оценивается как (void 0), пока глупый программист не вводит теневую undefined локальную переменную и не выполняет повторную привязку window.undefined. (Я считаю этот код нарушителем, а не код с использованием undefined.) - person user2864740; 18.11.2013
comment
@ user2864740 Если подумать, я согласен (конечно!) с тем, чтобы не использовать круглые скобки (мне пришлось быть слепым, когда впервые прочитал комментарий Myka Eyl!:]). Но я не согласен со второй частью. Причина, по которой вы должны использовать typeof d === 'undefined' вместо d === undefined, заключается в том, что при первом подходе вам не нужно заботиться о глупых разработчиках. Поскольку мир переполнен глупыми разработчиками, нам нужно тратить время на кодирование, а не на то, чтобы предвидеть возможные попытки глупых разработчиков испортить наш код, верно? :] - person trejder; 18.11.2013
comment
@trejder Я никогда не сталкивался с этой проблемой. Любая среда, в которой undefined было переопределено на значение, отличное от (void 0), является средой, которую я не поддерживать. (В Python 2.x True и False были просто переменными - например, True,False=False,True допустимо - но никогда не было никакого толчка, чтобы найти безопасный метод.) - person user2864740; 18.11.2013
comment
@trejder Поскольку мир переполнен глупыми разработчиками, нам нужно тратить время на собственное кодирование, а не на то, чтобы предвидеть возможные попытки глупых разработчиков испортить наш код, верно? = ›Следуя этой мысли, не typeof(d) === 'undefined' попытка предвидеть возможные попытки глупых разработчиков разрушить наш код? Если бы кто-то действительно переопределил undefined, я бы не стал доверять им, чтобы они не сделали что-то еще, чтобы сломать ваш код. - person Bob; 17.01.2014
comment
@RobQuist Он почти наверняка имел в виду перевернутый по сравнению с тем, что находится в коде, а не как приглашение к повторной войне за независимость. - person McGuireV10; 21.05.2014
comment
Как отмечали предыдущие комментаторы, это не только сбивает с толку, но и неправильно. Это дает 49.65.formatMoney (1, '.', ',') = ›49.6 - person hlascelles; 09.12.2014
comment
Я использовал это, но получил ошибку, поэтому добавляю var myMoney = Number (myMoney) .toFixed (2); добавление Number () сработало. - person CookieCoder; 11.12.2014
comment
В этих комментариях так много ссор. Вау, конечно, код может быть не самым красивым, но если вы достойны вашей соли как «программист», он определенно не слишком сложный или неразборчивый, если вы умеете читать код, конечно. И кто хоть раз поддерживает код, который они скопировали, но не создали сами? - person Deji; 26.11.2015
comment
@Deji, к черту стандарты стиля кодирования, именование вещей, структурирование кода, комментирование и аннотирование. - person aross; 16.12.2015
comment
@aross Связан ли этот вопрос со стандартами стиля кодирования, именованием вещей, структурированием кода, комментированием и аннотацией? Вы неопределенно упоминаете какую-либо из этих концепций, приводя какие-либо причины, по которым приведенный выше конкретный код не является подходящим ответом? Нет... - person Deji; 16.12.2015
comment
@Deji Значит, вы даже считаете обфусцированный код хорошим ответом? - person aross; 16.12.2015
comment
@aross Зависит от вопроса. Я думаю, что вы здесь не понимаете - комментарии предназначены не для оценки качества кода, а для оценки качества ОТВЕТА. Мне действительно не нужно объяснять, как обычно оценивают качество ответов на вопросы ... - person Deji; 16.12.2015
comment
К счастью, это вики сообщества, так что любой из вас, жалующийся на формат / удобочитаемость кода, может просто исправить это самостоятельно. - person Kevin B; 16.12.2015
comment
Эта функция неверна: ›(2030) .formatMoney (0, '.', ''); ‹2 03 0 - person Anton P Robul; 18.03.2016
comment
Странный код, на мой взгляд, напр. value дважды повторно назначается внутри функции, что очень затрудняет отладку. Если decimalPlaces = 0, значение неявно округляется на toFixed, что в моем случае не имеет отступа. - person wosis; 28.04.2016
comment
Как такая ужасная практика получила 1K + голосов? Не говоря уже о том, что он был написан предварительно. - person ; 31.08.2016
comment
Поскольку мне не нравится код, который я не могу прочитать, я переписал его, чтобы он был удобнее для разработчиков: syntaxwarriors.com/p/18/Format-currency-in-Javascript Практически то же самое, но читабельно. - person JensB; 20.12.2016
comment
Неминифицированная версия: josscrowcroft.com/2011/code / (см. Формат денег JavaScript). - person Victor Dombrovsky; 30.12.2016
comment
Прототип toLocaleString() делает то же самое с меньшим количеством кода. и более надежен. Ответили здесь - person Mark Carpenter Jr; 27.06.2017
comment
Я лично считаю это решение мусором. Вы не используете разумные имена переменных, вы изменяете prototype встроенного с помощью свойства enumerable, и ваш код даже не имеет смысла, даже если он действительно работает. - person Patrick Roberts; 18.07.2017
comment
Этот ответ сейчас несколько устарел. См. ответ о формате Intl.number ниже - person Captain Hypertext; 10.11.2017
comment
Код на этом сайте должен быть удобочитаемым для людей, а не для веб-браузеров. - person Bacon Brad; 22.06.2018
comment
Если дата может быть нулевой, вам нужно вызвать функцию следующим образом: formatMoney(someDate, 2) вместо someDate.formatMoney(2), иначе вы получите Uncaught TypeError: Cannot read property 'value' of null, when it is. - person Robin Wilson; 15.12.2018
comment
Я удивлен, что никто не упомянул, что строка j = (j = i.length) > 3 ? j % 3 : 0; вызывает j до того, как она будет определена - person Caio Mar; 31.05.2019
comment
Этому коду сложно следовать. По крайней мере, дайте некоторые имена параметрам. - person Jakub Keller; 08.06.2019
comment
ПРЕДУПРЕЖДЕНИЕ! Код, не относящийся к ES6, не работает по состоянию на 31.10.2019, я удивлен, что он получил столько голосов! Исправьте следующие простые случаи: 100000 (результат 100000,00) и 1000000 (результат 1,000000,00) - person ryanm; 31.10.2019
comment
Код, отличный от ES6, не работает, что-то не так с используемым regExpression, я годами не обновлял свой reg ex, поэтому я не могу его исправить, к сожалению - person beliha; 28.11.2019
comment
Очиститель не ES6: функция formatMoney (количество, десятичное число, десятичное число, тысячи) {decimalCount = Math.abs (decimalCount); decimalCount = isNaN (decimalCount)? 2: decimalCount; var negativeSign = amount ‹0? -:; var i = parseInt (amount = Math.abs (Number (amount) || 0) .toFixed (decimalCount)). toString (); var j = (i.length ›3)? i.length% 3: 0; return negativeSign + (j? i.substr (0, j) +,000: '') + i.substr (j) .replace (/ (\ d {3}) (? = \ d) / g, $ 1 + тысячи ) + (decimalCount? decimal + Math.abs (количество - i) .toFixed (decimalCount) .slice (2):); } - person beliha; 07.03.2020
comment
есть ли способ опровергнуть этот ответ. это больше не актуально. - person user1556937; 26.06.2020
comment
Все просто проголосуют против этого ответа, чтобы правильный ответ был более заметным. - person TheGeekZn; 09.11.2020
comment
Я хотел бы назвать этот ответ самым популярным ответом, который, ради всего святого, должен быть отвергнут. - person Martin Braun; 24.11.2020
comment
Код пользовательской функции неверен. Например, при запуске фрагмента кода 1234567.12 возвращается как 1,234567.12, это просто неправильно. - person Mike Jarema; 18.02.2021
comment
Мне пришлось добавить строку let j = 0; перед использованием j. Проблемы с кодом у некоторых разработчиков браузеров ... Но в других случаях все еще работает. Странный. - person JotaPardo; 26.04.2021
comment
хорошая работа, это очень полезно - person deemi-D-nadeem; 25.06.2021

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

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

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

ИСПЫТАНИЯ:

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

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


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

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

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

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

ДЕМО / ТЕСТЫ: http://jsfiddle.net/hAfMM/435/


Супер удлиненное короткое решение

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

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

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

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

ДЕМО / ТЕСТЫ: http://jsfiddle.net/hAfMM/612/

person Community    schedule 20.01.2013
comment
На самом деле я пошел еще дальше: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"). - person kalisjoshua; 21.03.2013
comment
Версия CoffeeScript с регулярным выражением VisioN и kalisjoshua и способом указания десятичного разряда (так что вы можете оставить значение по умолчанию 2 или указать 0 без десятичного числа): Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1," - person Eric Anderson; 18.06.2013
comment
Если мы вызовем toFixed (0), запятые исчезнут, есть идеи, как заставить его работать с this.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "$1,")? - person Abbas; 14.08.2013
comment
@Abbas Да, замените \. на $ (конец строки), то есть this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,"). - person VisioN; 15.08.2013
comment
Привет, @VisioN, не могли бы вы объяснить регулярное выражение и важность 1 доллара. Я использовал функцию регулярного выражения, но пропустил $ в $ 1. Значит, результат оказался неверным. Помогу мне, если сможешь объяснить. TIA. - person hanumant; 22.10.2013
comment
@hanumant Обычная грамматика здесь немного сложна, поэтому я предлагаю вам сначала прочитать руководства по регулярным выражениям (например, на MDN). Идея заключается в замене совпавших разделов первым совпадением и запятой, то есть $1,. Сопоставление выполняется с использованием подхода опережающего просмотра. Вы можете читать выражение как соответствует числу, если за ним следует последовательность из трех наборов чисел (один или несколько) и точка. - person VisioN; 22.10.2013
comment
@VisioN в случае значений по бразильским стандартам (1,222,333,44 реалов), получающих (122233344). Как это сделать? Я безуспешно пробовал изменить скрипку. Не могли бы вы мне помочь? (или даже добавьте формат 3 в свой пример, если особо не о чем просить). Я знаю, что принятый ответ охватывает это, но и ваш тоже отличный - person Michel Ayres; 17.03.2014
comment
@Michel Вот супер-расширенная версия, которая поддерживает разные типы разделителей: jsfiddle.net/hAfMM/610. - person VisioN; 17.03.2014
comment
@VisioN: Ваше короткое решение не работает для длинных номеров. Необходимо заменить \. на a \ b (от слова boudarie), как я предложил 4 января 2012 года (см. ниже). - person Julien de Prabère; 25.03.2014
comment
@ JuliendePrabère Приведите пример длинного числа, которое не работает при таком подходе. - person VisioN; 25.03.2014
comment
@ Gyrocode.com Почему $& подход вам не подошел? - person VisioN; 16.06.2015
comment
Дополнительная суперрасширенная версия: jsfiddle.net/hAfMM/2269 Интегрирует символ валюты - person Pier-Luc Gendreau; 16.06.2015
comment
Почему это не лучший ответ? Он рассмотрел все возможные варианты - person Clain Dsilva; 12.09.2015
comment
хорошо, классный код, к сожалению, я многое не понимаю, но это было очень полезно, спасибо - person Andres Felipe; 11.12.2015
comment
@ 1111161171159459134 Это всего лишь короткая и быстрая альтернатива Math.floor(n). Если вы хотите сделать его совместимым с JSHint, замените этот бит соответствующим образом. - person VisioN; 18.06.2016
comment
Отличный код. Можно ли сделать обратное, например неформатирование (от 12.345.678,90 до 12345678.9), аналогично любому денежному формату с обычным числом @VisioN - person Mohammed Farooq; 20.09.2016
comment
@MohammedFarooq Конечно, это так просто: jsfiddle.net/hAfMM/3934. - person VisioN; 21.09.2016
comment
@ VisioN - Спасибо, но мне не нужно передавать (запятую и точку) в качестве параметра. Мне нужно вернуть число, если я прохожу (от 12,345,678,90 до 12345678,9) или (от 12,345,678,90 до 12345678,9). EI Другой евро или стандартный формат на обычный номер - person Mohammed Farooq; 21.09.2016
comment
@MohammedFarooq Чтобы это работало, скрипт должен знать, в каком стиле отформатирован ваш номер. Он не может автоматически определить, используется ли точка или запятая в качестве разделителя для разделов или десятичной части. В противном случае вам придется использовать строгий числовой формат, чтобы синтаксический анализатор мог угадать, какой символ от какой части разделяет. - person VisioN; 21.09.2016
comment
Как мне отформатировать номер 12514652? Я не могу называть 12514652.format() рубином ... так? - person Matrix; 22.09.2016
comment
Спасибо за Ваш ответ. Но у меня есть вопрос: как убрать e + из числа? например, 1000000000000000000000 теперь форматируется как: $ 1e + 21, но я бы хотел, чтобы это было так: $ 1,000,000,000,000,000,000,000.00 - person Besat; 20.10.2016
comment
@Besat Это сложный вопрос, но мы можем использовать хороший обходной путь с помощью специального метода Number.prototype.toFixed, который может неявно преобразовывать числа в экспоненциальной нотации в их полноразмерное строковое представление. См. Решение здесь: jsfiddle.net/hAfMM/4027. - person VisioN; 20.10.2016
comment
Чудесно! Спасибо! - person Besat; 20.10.2016
comment
как сделать пример arr [i] .price, отформатированный под это? этот код отлично работает! @Зрение - person Faisal; 04.11.2016
comment
@aross К сожалению, Intl API по-прежнему недоступен во многих широко используемых браузерах, и это решение сделает смысл, когда требования совместимости включают IE9, IE10, Safari 9 и т. д. - person VisioN; 04.01.2017
comment
@aross Часто включение 2-3 строк кода быстрее и проще, чем встраивание библиотеки объемом 50+ КБ, чтобы получить тот же результат. Это зависит от того, что вы на самом деле делаете. Я до сих пор использую этот код в своих проектах, когда мне просто нужно отформатировать число в простом формате. - person VisioN; 04.01.2017
comment
@aross Мой опыт говорит об обратном: этого кода хватает в 90% случаев. Я не знаю, что такое группировка индейских цифр, но уверен, что это решение можно легко настроить под нее. Поймите меня правильно, я не говорю, что этот ответ является лучшим на сегодняшний день в 2017 году, но я вполне уверен, что разработчики все равно найдут его полезным. - person VisioN; 04.01.2017
comment
VisioN, вы правы - я выбираю первое из ваших коротких решений, которое, кстати, является великолепным регулярным выражением! Спасибо, что поделились, у меня появился нейрон. - person Gerard ONeill; 27.04.2017
comment
Моя версия TS, которая работает во многих случаях: export const formatNumberToUSFormat = (numberToFormat: number | string) => { const stringNumber = numberToFormat.toString() return stringNumber.match(/\./g) ? stringNumber.replace(/\d(?=(\d{3})+\.)/g, '$&,') : stringNumber.replace(/\d(?=(\d{3})+$)/g, '$&,') } - person Avernikoz; 12.10.2018
comment
Это отличное решение! но я пробовал использовать его для числа, начинающегося с 0, например (012345).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,') Он возвращает 5 349,00 вместо 12 345,00 - person olaoluwa_98; 12.05.2020
comment
@ olaoluwa_98 Числа, начинающиеся с нуля, считаются восьмеричными литералами, поэтому 012345 5349 в десятичной системе счисления. Вам не разрешено использовать восьмеричные литералы в строгом режиме. - person VisioN; 12.05.2020
comment
Мои 2 цента: для неимперских (истов) парней(7642818.78).toFixed(2).replace(".",",").replace(/\d(?=(\d{3})+\,)/g, '$&.') - person Paulo Bueno; 30.09.2020
comment
Как это сделать с событием на входе при наборе текста? - person guilieen; 30.11.2020
comment
Эти встроенные функции форматирования несовместимы (требуются данные локали ...), поэтому это регулярное выражение - спаситель. - person wilmol; 20.01.2021

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

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

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

Пример:

Number((someNumber).toFixed(1)).toLocaleString()
person Community    schedule 29.09.2008
comment
Спасибо! На основе этой идеи я смог сделать достаточно короткий и простой! (и с локализацией) Отлично. - person Daniel Magliola; 29.09.2008
comment
На самом деле можно. то есть для долларов: '$' + (значение + 0,001) .toLocaleString (). slice (0, -1) - person Zaptree; 18.11.2013
comment
Похоже, это было бы здорово, но на данный момент поддержка браузеров невелика. - person acorncom; 06.12.2013
comment
Safari определенно реализует функции toLocale иначе. Форматы даты локали также производят другой вывод, чем любой другой основной браузер. - person Neil Monroe; 26.06.2014
comment
@acorncom Почему вы говорите, что браузеры мало поддерживают? Объект Number существует с Javascript 1.1. Предоставьте ссылку, подтверждающую вашу претензию. - person Doug S; 31.08.2015
comment
Следует позаботиться о том, чтобы существовала старая версия toLocaleString, использующая системный языковой стандарт, и новая (несовместимая) версия, исходящая от ECMAScript Intl API. Объясняется здесь. Этот ответ, похоже, предназначен для старой версии. - person aross; 14.09.2017
comment
Не уверен, почему за это так проголосовали, но это не соответствует тому, о чем просит OP. Например, 10000 превратится в "10,000", а не "10,000.00", что является желаемым поведением для форматирования валюты. - person Burak; 07.06.2018
comment
По поводу комментария @Burak. Я не думаю, что это так. Для меня код var currency = $ + Number (someNumber.toFixed (2)). ToLocaleString () превращает var someNumber = 2345667.7899; на $ 2 345 667,79, что мне и нужно. - person Alexander; 10.06.2018
comment
@Alexander, а что, если someNumber 234567 или 234567,8? Тогда у вас будет ноль или один десятичный знак вместо двух, что не то, чего хочет OP, и, как правило, кажется нежелательным и для форматирования валюты. - person Burak; 18.06.2018
comment
Да вы правы. Сейчас я использую прототип Number.prototype.formatMoney, который указан ниже. - person Alexander; 20.06.2018
comment
лучший ответ на сегодняшний день - person oldboy; 12.08.2019
comment
Number () является обязательным, если переменная является строкой или любым другим типом. Это мне очень помогло! спасибо, что поделились этим. - person acido; 08.11.2019
comment
Я согласен с @Burak, почему это пока лучший ответ .. кто-нибудь пробовал? он не дает ожидаемого результата - person Cegone; 16.06.2020

Ниже представлен Патрик Дежардинс (псевдоним Даок) код с небольшими комментариями и небольшими изменениями:

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

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

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

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

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

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

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

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

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

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

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

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

  4. (+n || 0) не требуется, потому что this является Number объектом

JSFiddle

person Community    schedule 19.05.2010
comment
Вы можете использовать «10» в качестве основания в parseInt. В противном случае для любого числа, начинающегося с «0», будет использоваться восьмеричная нумерация. - person sohtimsso1970; 15.11.2011
comment
@ sohtimsso1970: извините за поздний ответ, но не могли бы вы объяснить еще кое-что? Я не понимаю, где число может интерпретироваться как восьмеричное. parseInt вызывается для абсолютного значения целой части числа. Часть INTEGER не может начинаться с ZERO, если только это не просто ZERO! И parseInt(0) === 0 либо восьмеричный, либо десятичный. - person Marco Demaio; 09.02.2012
comment
попробуйте, например: parseInt (016) ... возвращает 14, поскольку parseInt предполагает, что он закодирован в восьмеричной системе, когда строка начинается с нуля. - person Tracker1; 20.03.2012
comment
@ Tracker1: Я понял, что число, начинающееся с 0, считается восьмеричным по parseInt. Но в этом коде НЕВОЗМОЖНО для parseInt получить 016 в качестве ввода (или любое другое восьмеричное форматированное значение), потому что аргумент, переданный в parseInt, является 1-м обработанным функцией Math.abs. Таким образом, parseInt не может получить число, начинающееся с нуля, если только это не просто ноль или 0.nn (где nn - десятичные числа). Но обе строки 0 и 0.nn будут преобразованы parseInt в простой НУЛЬ, как и предполагалось. - person Marco Demaio; 20.03.2012
comment
Эта функция неверна: ›(2030) .toMoney (0, '.', ''); ‹2 03 0 - person Anton P Robul; 18.03.2016
comment
@AntonPRobul это неправда, вы можете проверить это с помощью ссылки JS FIddle, добавленной в ответ, (2030).toMoney(0, '.', ' '); дает следующее: "2 030", что является ожидаемым результатом, поскольку вы указываете функции использовать один пробел в качестве разделителя тысяч. - person Marco Demaio; 31.01.2021
comment
Мне пришлось добавить строку let j = 0; перед использованием j. Проблемы с кодом у некоторых разработчиков браузеров ... Но в других случаях все еще работает. Странный. - person JotaPardo; 26.04.2021

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

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

создаст строку "-$123.00".

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

person Community    schedule 04.11.2014
comment
Этот ответ был почти у меня, но мне нужно было округлить его до ближайшего пенни. Это то, что я использовал amount.toLocaleString ('en-GB', {style: 'currency', currency: 'GBP', maximumFractionDigits: 2}); - person Nico; 18.11.2014
comment
Приведенный выше код округляет до желаемого количества цифр. См. Пример и введите 1,237 в поле ввода. - person Daniel Barbalace; 26.03.2015
comment
Кажется, не работает в Safari. Он просто возвращает число в виде строки без какого-либо форматирования. - person Lance Anderson; 08.05.2015
comment
Документация по MDN для всех, кто хотел бы увидеть полный набор опций. - person Mark Carpenter Jr; 27.06.2017
comment
Вау, это действительно отличный ответ. Должно быть наверху. - person Ethan; 15.07.2017
comment
Если по какой-то причине вам не нужны центы, вы можете изменить десятичную точность с помощью: minimumFractionDigits: 0 - person Horacio; 29.05.2018
comment
@Horacio / Nico - см. Предыдущий ответ: stackoverflow.com/a/18994850/782034 - person Nick Grealy; 18.05.2019

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

person Community    schedule 01.09.2011
comment
... просто не забудьте передать символ валюты, иначе он выйдет из строя в IE7 и IE8, IE9 в любом случае в порядке - person vector; 08.10.2011
comment
Похоже, ошибка IE7 / IE8 исправлена. - person Mat Schaffer; 17.01.2012
comment
Это отличная библиотека, возможность передавать символ валюты также является хорошей идеей, поскольку все детали валюты содержатся в одном вызове / настройках функции. - person farinspace; 20.10.2012
comment
Мне нравится то, что вы можете сделать обратное - передать отформатированную строку валюты и получить числовое значение. - person Neil Monroe; 26.06.2014
comment
Продолжайте голосовать за это, так как это лучшее решение (если не лучший ответ). - person Ted; 05.03.2015
comment
account.js, похоже, не поддерживается в последнее время. Одна вилка с недавними изменениями - github.com/nashdot/accounting-js. - person RationalDev likes GoFundMonica; 21.04.2016

Вот лучший форматер денег JavaScript, который я видел:

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

Он был переформатирован и заимствован отсюда: Как отформатировать числа как строки валюты

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

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

var myMoney = 3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2, ',', '.'); // "$3,543.76"
person Community    schedule 16.02.2012
comment
следите за глобальным знаком, i, j - person hacklikecrack; 20.11.2013
comment
@hacklikecrack, все переменные локальные; они в заявлении var. - person Jonathan M; 20.11.2013
comment
извините, да, хотя вы пересказываете аргументы. Отступ! ;) - person hacklikecrack; 25.02.2014
comment
Ужасное использование имен переменных! - person Serj Sagan; 09.04.2018

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

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"

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

person Community    schedule 17.03.2011
comment
поэзия. блестящий. пробовали ли вы reduceRight () developer.mozilla.org/en/JavaScript/ Ссылка / Global_Objects /, что должно устранить обратную ()? - person Steve; 21.12.2011
comment
@Steve - Вы правы, но вам нужно сделать что-то вроде i = orig.length - i - 1 в обратном вызове. Тем не менее, на один обход массива меньше. - person Wayne; 21.12.2011
comment
Не о совместимости: метод reduce был введен в Ecmascript 1.8 и не поддерживается в Internet Explorer 8 и ниже. - person Blaise; 10.05.2012
comment
Как сказал @Blaise, этот метод не будет работать в IE 8 или ниже. - person rsbarro; 01.08.2013
comment
Да, конечно, правильно. Как отмечено в самом ответе, это просто для развлечения. Кроме того, он должен нормально обрабатывать отрицательные числа. - person Wayne; 17.09.2013
comment
Отрицательные числа у меня работали нормально. Что мне нравится в этом, так это то, что кода не так много, и он не зависит от регулярного выражения. - person Betty Mock; 15.01.2015
comment
Почему ты просто не сделал (parseInt(p[0])).toLocaleString()? - person Chase Sandmann; 16.06.2015
comment
Потому что эта функция может давать разные результаты в разных регионах. Это вполне может быть то, что вы хотите, но это не дает прямого ответа на конкретный вопрос о форматировании. (Также обратите внимание на дату в вопросе / ответах здесь.) - person Wayne; 17.06.2015
comment
чтобы правильно обрабатывать отрицательное число, добавьте следующий код перед возвратом num=="-" ? acc: ‹br› т.е. функция, переданная в метод уменьшения, будет ‹br› function(acc, num, i, orig) { return num=="-" ? acc:num + (i && !(i % 3) ? "," : "") + acc; } - person Akshay Vijay Jain; 07.12.2016
comment
Но как это сделать в валюте евро? - person ; 06.06.2017
comment
Редактирование для поддержки отрицательных чисел на самом деле не работает - person Wayne; 04.05.2021

Работает для всех текущих браузеров.

Используйте toLocaleString для форматирования валюты в ее зависимом от языка представлении (используя Коды валют ISO 4217).

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

Примеры фрагментов кода южноафриканского рэнда для avenmore:

console.log((2500).toLocaleString("en-ZA", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> R 2 500,00
console.log((2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}))
// -> ZAR 2,500.00

person Community    schedule 25.09.2013
comment
Поскольку аргументы «locales» и «options» поддерживаются очень небольшим количеством браузеров, например Chrome 24, IE11 и Opera 15. Firefox, Safari и другие более старые версии по-прежнему не поддерживают его. - person VisioN; 25.09.2013
comment
Согласен, он не полностью поддерживается во всех браузерах (пока), но все же является решением. (И, возможно, наиболее верное решение, поскольку оно полностью совместимо с неподдерживаемыми браузерами, и это задокументированная функция Javascript api.) - person Nick Grealy; 26.09.2013
comment
Мне это нравится, и я рад, что он работает с индийской группировкой цифр. - person MSC; 03.07.2016
comment
Это полностью поддерживается по состоянию на 2017 год и должно быть единственно правильным ответом. - person Evgeny; 14.04.2017
comment
Это не дает правильного общепринятого формата для en-ZA / ZAR (Южная Африка), поэтому, если вы находитесь в отдаленном регионе, вы можете зависеть от того, каким, по мнению постороннего, должен быть ваш формат. - person avenmore; 19.08.2019
comment
@avenmore работает с последними версиями Chrome / Firefox / Safari. Ненавижу спрашивать ... но в каком браузере и какой версии вы тестируете? - person Nick Grealy; 20.08.2019
comment
Последний и лучший :) FF69, Chrome76 и т. Д. 2 500,00 рэнд - это не то, что мы здесь используем, это должно быть 2 500,00 рэнд, как en-GB. - person avenmore; 20.08.2019
comment
@avenmore ... интересно ... Я провел небольшое расследование и TL; DR; запятая - официальный десятичный разделитель для Южной Африки. Когда Южная Африка приняла метрическую систему, она приняла запятую в качестве десятичного разделителя, хотя в ряде домашних стилей, в том числе в некоторых англоязычных газетах, таких как The Sunday Times, по-прежнему используется точка - en.wikipedia.org/wiki/Decimal_separator. Однако вы можете переключать форматы, используя (2500).toLocaleString("en-GB", {style: "currency", currency: "ZAR", minimumFractionDigits: 2}) - person Nick Grealy; 20.08.2019
comment
@Nick Grealy Спасибо за расследование, это проклятие южноафриканских программистов - когда вещи ломаются после неожиданной запятой. Я пробовал параметры, которые вы предлагаете, но они дали 2500,00 южноафриканских рэндов, что тоже неприемлемо. - person avenmore; 20.08.2019
comment
minimumFractionDigits: 2 именно то, что я искал! - person Tim; 24.10.2019

Я думаю, ты хочешь:

f.nettotal.value = "$" + showValue.toFixed(2);
person Community    schedule 16.02.2012
comment
@ crush это работает, но больше не переносит расчеты в налоговое поле? - person Rocco The Taco; 17.02.2012
comment
После того, как вы добавите к нему знак $, это уже не число, а строка. - person crush; 17.02.2012
comment
Эта опция не ставит запятую между тысячами. :-( - person Simon East; 09.10.2019

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

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 только для того, чтобы сделай это :-) )

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

person Community    schedule 29.09.2008
comment
Обратите внимание, что ваша версия неправильно округляет до двух десятичных цифр. Например, 3,706 будет отформатировано как 3,70 фунта стерлингов, а не как 3,71 фунта стерлингов, как должно быть. - person Ates Goral; 01.10.2008
comment
Да, в моем конкретном случае это нормально, поскольку суммы, с которыми я работаю, уже имеют не более 2 цифр. Причина, по которой мне нужно исправить до 2 десятичных знаков, - это суммы без десятичных знаков или только с 1. - person Daniel Magliola; 02.10.2008

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

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
person Community    schedule 02.10.2012
comment
Форк Numbro, кажется, получает больше любви, поскольку Numeral.js кажется заброшенным: github.com/foretagsplatsen/numbro - person RationalDev likes GoFundMonica; 21.04.2016
comment
Numeral.js снова активен. - person adamwdraper; 03.12.2016

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

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

person Community    schedule 22.07.2011
comment
Вау, почему за это не проголосовали больше? Большая стандартизированная библиотека для всевозможного форматирования. Стандартные для отрасли параметры форматирования с правильной глобализацией. Отличный ответ !! - person pbarranis; 10.09.2013
comment
Это все еще считается альфа-стадией, поэтому используйте осторожно, но отличная находка. - person Neil Monroe; 26.06.2014
comment
Больше не в альфа (или бета). Это кажется очень полезным, пока мы ждем, пока Safari будет соответствовать новому стандарту, а IE ‹11 умрет. - person Guy Schalnat; 21.08.2015

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

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

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

person Community    schedule 16.07.2011

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

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

    n = 12345678.9;
    alert(n.toCurrencyString());
person Community    schedule 04.01.2012
comment
Это потрясающе! Должны быть лучшие ответы! - person Harrison; 03.03.2021

Следующее краткое, легкое для понимания и не основывается на каких-либо чрезмерно сложных регулярных выражениях.

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

person Community    schedule 17.10.2016
comment
Отличный фрагмент кода, спасибо. Однако будьте осторожны, так как это не будет работать в IE, потому что параметры по умолчанию не поддерживаются, а const и let не поддерживаются в ‹IE11. Используйте это, чтобы исправить: + moneyFormat: function (price, sign) {+ if (! Sign) sign = '$'; + piece = parseFloat (цена) .toFixed (2) .split ('') + var ii = piece.length - 3 - person Charlie Dalsass; 21.11.2016
comment
Не беспокойся @CharlieDalsass. Я бы рекомендовал использовать babel, чтобы скомпилировать его до ES5 для производственного кода. - person synthet1c; 23.11.2016
comment
Но как сделать евро валютой? 1.000,00 евро? - person ; 06.06.2017
comment
@YumYumYum Я добавил полный пример с большим количеством параметров форматирования, чтобы обеспечить большую гибкость. - person synthet1c; 07.06.2017

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

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

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

    return sign + currencySymbol + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
person Community    schedule 30.06.2012
comment
Первая переменная выглядит довольно странно, поскольку эти переменные уже объявлены в объявлении функции. Кроме этого, спасибо! - person Rich Bradshaw; 22.03.2013
comment
Ты прав. Это ошибка, которую я перенес из оригинала Джонатана М., где все они связаны как одно выражение var. Это должны быть простые задания. Исправление. - person XML; 18.10.2013
comment
В этом отношении я думаю, что это, вероятно, преждевременно оптимизировано и должно быть переработано для удобства чтения. Но моей целью было дополнить код OP, а не принципиально его изменить. - person XML; 18.10.2013
comment
Это не так уж и плохо - +n || 0 - единственное, что кажется немного странным (по крайней мере, мне). - person Rich Bradshaw; 18.10.2013
comment
this - очень полезное имя переменной. Преобразование его в n, чтобы вы могли сохранить 3 символа во время определения, возможно, было необходимо в эпоху, когда ОЗУ и пропускная способность считались в КБ, но это просто запутывание в эпоху, когда минификатор позаботится обо всем этом, прежде чем он когда-либо попадет в производство. . Остальные умные микрооптимизации по крайней мере спорны. - person XML; 18.10.2013
comment
Верно - не поймал. - person Rich Bradshaw; 19.10.2013
comment
если кто-то хочет отменить formatMoney, вот код: String.prototype.undoFormatMoney = function () {var tempVals; var val = это; var sign = ((val.split ('$') [0]) == -)? -:, val = val.split ('$') [1]; tempVals = val.split (','); val = 0; var adjPlaces = 1; len1 = (tempVals.length) - 1; for (var i = len1, j = 0; i ›= 0; i--, j ++) {if (j› 0) {adjPlaces = j * 1000; } val = val + ((tempVals [i]) * adjPlaces); } знак возврата + + val; }; - person nikhil; 17.06.2014

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

<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)));">
person Community    schedule 29.09.2008
comment
Я получаю неправильный вывод числа при вводе отрицательных значений в ins1000Sep (). - person Peter; 11.08.2015

Есть порт JavaScript для функции PHP number_format.

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

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

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

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

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

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

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

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

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

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

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

Ответ Патрика Дежардена выглядит неплохо, но я предпочитаю простой код 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];
}
person Community    schedule 16.04.2012
comment
Мне нужно, чтобы что-то работало как в браузере, так и в старой версии Node. Это сработало отлично. Спасибо - person n8jadams; 13.08.2019

В JavaScript есть встроенная функция toFixed:

var num = new Number(349);
document.write("$" + num.toFixed(2));
person Community    schedule 17.02.2012
comment
Этот ответ выглядит излишним. Ответ Crush уже был дан toFixed() - person Ian Dunn; 25.09.2012
comment
toFixed() является функцией объекта Number и не будет работать с var num, если он был String, поэтому мне помог дополнительный контекст. - person timborden; 20.11.2012

function CurrencyFormatted(amount)
{
    var i = parseFloat(amount);
    if(isNaN(i)) { i = 0.00; }
    var minus = '';
    if(i < 0) { minus = '-'; }
    i = Math.abs(i);
    i = parseInt((i + .005) * 100);
    i = i / 100;
    s = new String(i);
    if(s.indexOf('.') < 0) { s += '.00'; }
    if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
    s = minus + s;
    return s;
}

Из WillMaster.

person Community    schedule 29.09.2008
comment
Маленький и простой. Спасибо. - person Connor Simpson; 28.07.2016
comment
просто, но без запятой для 1000 - person aron; 19.03.2018

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

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

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

formatter.formatValue(1000000); // $ 1,000,000
person Community    schedule 02.10.2012

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

Объявите это в любом месте вашего HTML-раздела ‹head› или там, где это необходимо, непосредственно перед тем, как вам понадобится его использовать:

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

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

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

Как обычно, есть несколько способов сделать одно и то же, но я бы не стал использовать 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);
    }
}
person Community    schedule 19.07.2010
comment
Смысл toLocaleString в том, что он настраивается в соответствии с настройками пользователя. - person Joseph Lennox; 15.08.2013

* Попробуйте следующий код

"250000".replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');

Ответ: 250 000

Введите здесь описание изображения

person Community    schedule 26.03.2020

Вот некоторые решения, и все они проходят тестовый набор. Набор тестов и тест включены. Если вы хотите скопировать и вставить для проверки, попробуйте эту суть.

Метод 0 (RegExp)

Он основан на ответе VisioN, но исправляет если нет десятичной точки.

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

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

Способ 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's before the first thousands separator
        head += (a[0].length - head) % 3 || 3;

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

Метод 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);

Контрольный показатель

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

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

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

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
person Community    schedule 17.05.2014
comment
Улучшено по сравнению с вашим методом 2. измените значение var a = this.toFixed (precision) .split ('.') На var multiplier = Math.pow (10, precision + 1), wholeNumber = Math.floor (this * multiplier) ; var a = Math.round (wholeNumber / 10) * 10 / множитель; if (String (a) .indexOf ('.') ‹1) {a + = '.00'; } a = String (a) .split ('.'), не используйте toFixed, потому что он содержит ошибки. - person vee; 18.10.2014
comment
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 десятичная дробь всех этих значений должна быть 0,84, а не 0,83. - person vee; 18.10.2014

Я нашел это из: 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€ 

person Community    schedule 04.06.2016
comment
$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) ); - показать 1.000,00 E - person ; 07.06.2017

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

String.prototype.reverse = function() {
    return this.split('').reverse().join('');
};

Number.prototype.toCurrency = function( round_decimal /*boolean*/ ) {       
     // format decimal or round to nearest integer
     var n = this.toFixed( round_decimal ? 0 : 2 );

     // convert to a string, add commas every 3 digits from left to right 
     // by reversing string
     return (n + '').reverse().replace( /(\d{3})(?=\d)/g, '$1,' ).reverse();
};
person Community    schedule 02.12.2011

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

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

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

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

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

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

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

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

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

        return sOutput;
    }
    // Still not a number. Just return it unaltered
    else {
        return nData;
    }
}

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

person Community    schedule 29.09.2008
comment
Слишком долго, и мне придется включить YUI - person Daniel Magliola; 29.09.2008
comment
Моя первая реакция была лол - слишком долго, YUI отстой ... но после пересмотра, это неплохой код, просто очень ... полный. Он проверяет, действительно ли аргумент является числом (не выполняется другими плакатами, и это единственная часть, которая требует библиотеки YUI). Он округляет (не для всех плакатов). Он имеет настраиваемый разделитель, префикс и суффикс. Наконец, код комментируется и не использует регулярных выражений и сложных однострочных выражений. Итак ... я даю вам +1, чтобы компенсировать другим -1 ... этот код неплох - его можно адаптировать, даже если не использовать YUI. - person Nick Perkins; 15.11.2011
comment
В YUI они, должно быть, больны, не могут поверить, что написали такой кусок кода. - person Marco Demaio; 09.02.2012

Пример Патрика Дежардена (бывшего Даока) хорошо мне подошел. Я перенес его на 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
person Community    schedule 15.04.2011

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

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];
}
person Community    schedule 29.09.2008
comment
Извини, нет. Это удалит лишние десятичные разряды, но не исправит 2 десятичных разряда. 25 будет составлять 25 долларов США с вашим кодом, а не 25 долларов США. - person Daniel Magliola; 29.09.2008
comment
Все равно ошибаюсь! Вы используете toLocaleString, который может использовать десятичный разделитель вместо., И предполагая, что это. - person Daniel Magliola; 02.10.2008
comment
Это был минималистичный подход, отвечающий первоначальным расплывчатым требованиям, в которых в качестве примера было всего лишь 2500 долларов. - person Ates Goral; 03.10.2008

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

Date.prototype.toLocaleString ()

(Старое решение) Используйте решение Патрика Дежардена.

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

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

См. Интернационализация и локализация, Валюты для получения дополнительной информации.

person Community    schedule 04.05.2015
comment
Не согласовано во всех браузерах: / - person stackoverfloweth; 09.06.2015
comment
Спасибо за предупреждение @godmode. С какими браузерами вы столкнулись с проблемами? - person Ken Palmer; 09.06.2015
comment
Safari 8.0.6 не обрезал десятичные дроби, не вставлял $ или не добавлял запятые - person stackoverfloweth; 09.06.2015
comment
Возникла идея использовать toLocaleString (), но упала на поплавок. Как отмечалось ранее, валюта никогда не должна храниться в плавающем состоянии. - person tggagne; 19.08.2015
comment
Спасибо @tggagne, вы правы. Плохой контроль с моей стороны. - person Ken Palmer; 19.08.2015

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

Пример вывода:
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();
}
person Community    schedule 19.05.2014

Другой путь:

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;
}
person Community    schedule 22.10.2015
comment
Объяснение было бы в порядке. Например, в чем идея / суть? Чем он отличается от предыдущих ответов? - person Peter Mortensen; 01.05.2021

Мы также можем использовать numeraljs.

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

var string = numeral(1000).format('0,0');
// '1,000'
person Community    schedule 19.09.2019

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;
}
person Community    schedule 15.01.2013
comment
это просто скопировано из поиска Google. Проект не обновлялся с 2011 года. - person Luke Page; 20.11.2013

Intl.NumberFormat

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

Или number_format PHP в JavaScript.

person Community    schedule 10.09.2014
comment
Попросил решение JS! - person Bhargav Nanekalva; 26.06.2015
comment
@Bhargav Nanekalva: На самом деле это в JavaScript. - person Peter Mortensen; 27.05.2021
comment
Первая ссылка (фактически) не работает: Страница не найдена - person Peter Mortensen; 27.05.2021

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

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

var number = 123456,789;

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

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

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

person Community    schedule 22.10.2014

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

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

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

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 + "\"");
    }
}
person Community    schedule 15.08.2013

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

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

// usage: toCurrency(3939920.3030);
person Community    schedule 21.01.2014
comment
toCurrency('123456.7890') возвращает 123,456.7,890. ИМХО, в десятичных разрядах не должно быть запятых. В остальном выглядит хорошо! - person Mike Causer; 24.04.2014
comment
Как он может быть лучшим, если выводит неверный результат? - person Peter Mortensen; 27.05.2021

Код от Джонатана М выглядел для меня слишком сложным , поэтому я переписал его и получил около 30% на Firefox v30 и 60% на повышение скорости Chrome v35 (http://jsperf.com/number-formating2):

Number.prototype.formatNumber = function(decPlaces, thouSeparator, decSeparator) {
    decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
    decSeparator = decSeparator == undefined ? "." : decSeparator;
    thouSeparator = thouSeparator == undefined ? "," : thouSeparator;

    var n = this.toFixed(decPlaces);
    if (decPlaces) {
        var i = n.substr(0, n.length - (decPlaces + 1));
        var j = decSeparator + n.substr(-decPlaces);
    } else {
        i = n;
        j = '';
    }

    function reverse(str) {
        var sr = '';
        for (var l = str.length - 1; l >= 0; l--) {
            sr += str.charAt(l);
        }
        return sr;
    }

    if (parseInt(i)) {
        i = reverse(reverse(i).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator));
    }
    return i + j;
};

Использование:

var sum = 123456789.5698;
var formatted = '$' + sum.formatNumber(2, ',', '.'); // "$123,456,789.57"
person Community    schedule 26.06.2014

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

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

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

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

person Community    schedule 30.09.2016

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

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

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

person Community    schedule 11.05.2011
comment
Это работает? 10 лет должно хватить, чтобы разобраться. Или это риторический вопрос? - person Peter Mortensen; 27.05.2021

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

person Community    schedule 16.02.2012

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

Более быстрый способ с регулярным выражением:

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;
}
person Community    schedule 29.11.2011

Я во многом основывал это на ответе 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

Просто для развлечения.

person Community    schedule 21.03.2013

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

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

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

Сделаю немного длиннее:

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

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

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

Часть subst здесь означает:

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

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

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

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

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

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

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

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

1234567.89 -> 1,234,567

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

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

person Community    schedule 29.01.2015
comment
После десятичной дроби вам нужны только две (2) цифры, например, предположим, что ваш формат валюты - это 22.2737, в это время вы можете использовать следующее решение для получения результата в этом формате 22.27, функция currencyFormat (num) {return parseFloat (num) .toFixed (2); } var moneyWithDecimal = currencyFormat (22.2737); alert (moneyWithDecimal); - person Amzad Khan; 03.05.2020

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

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

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

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

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

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

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

    if(typeof(fmt) !== "undefined"){
        //...can be extended..., just add the char, for example "O":    MFX -> MFXO
        var rpatt = /(?:%([^%"MFX]*)([MFX]))|(?:"([^"]*)")|("|%%)/gi;
        var _qu = "\"";
        var _mask_qu = "\\\"";
        var str = fmt.toString().replace(rpatt, function($0, $1, $2, $3, $4){
                      var f;
                      if(typeof $1 !== "undefined"){
                          switch($2.toUpperCase()){
                              case "M": f = "_f_money(v)";    break;

                              case "F": var n_dig0, n_dig1;
                                        var re_flt =/^(?:(\d))*(?:[.](\d))*$/;
                                        $1.replace(re_flt, function($0, $1, $2){
                                            n_dig0 = $1;
                                            n_dig1 = $2;
                                        });
                                        f = "_f_flt(v, " + n_dig0 + "," + n_dig1 + ")";    break;

                              case "X": var n_dig = "undefined";
                                        var re_flt = /^(\d*)$/;
                                        $1.replace(re_flt, function($0){
                                            if($0 != "") n_dig = $0;
                                        });
                                        f = "_f_hex(v, " + n_dig + "," + ($2=="X") + ")";    break;
                              //...can be extended..., for example:    case "O":
                          }
                          return "\"+"+f+"+\"";
                      } else if(typeof $3 !== "undefined"){
                          return _mask_qu + $3 + _mask_qu;
                      } else {
                          return ($4 == _qu) ? _mask_qu : $4.charAt(0);
                      }
                  });

        var cmd =     "return function(v){"
                +     "if(typeof v === \"undefined\")return \"\";"  // null returned as empty string
                +     "if(!v.toFixed) return v.toString();"         // not numb returned as string
                +     "return \"" + str + "\";"
                + "}";

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

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

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

Поскольку мне не нужно форматировать что-то другое, кроме евро, я реализовал только% m.

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

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

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

//   but we use a complex example:

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

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

var v1 = formatter(1897654.8198344);

var v2 = formatter(4.2);

... (and thousands of rows)

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

В-третьих, формат, подобный вызову (значение, fmt), неприемлем, потому что:

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

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

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

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

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

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

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

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

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

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

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

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

var v_hex = (4.3282).format_hex();

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

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

person Community    schedule 20.02.2015
comment
Re множество ошибок в коде: три места, которые выглядят подозрительно: l=l-v.length (находится в логическом контексте / сравнение), return "\"+"+f+"+\""; (отсутствуют экраны?) И return new Function("_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex); (это допустимый синтаксис? - нет риторический вопрос). - person Peter Mortensen; 27.05.2021

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

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

var number = slimFormatter.currency(2000.54);
person Community    schedule 10.11.2016

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

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
person Community    schedule 06.04.2018

Я хотел ванильное решение 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");
person Community    schedule 30.07.2018

function getMoney(A){
    var a = new Number(A);
    var b = a.toFixed(2); // Get 12345678.90
    a = parseInt(a); // Get 12345678
    b = (b-a).toPrecision(2); // Get 0.90
    b = parseFloat(b).toFixed(2); // In case we get 0.0, we pad it out to 0.00
    a = a.toLocaleString(); // Put in commas - Internet Explorer also puts in .00, so we'll get 12,345,678.00
    // If Internet Explorer (our number ends in .00)
    if(a < 1 && a.lastIndexOf('.00') == (a.length - 3))
    {
        a = a.substr(0, a.length-3); // Delete the .00
    }
    return a + b.substr(1); // Remove the 0 from b, then return a + b = 12,345,678.90
}
alert(getMoney(12345678.9));

Это работает в Firefox и Internet Explorer.

person Community    schedule 27.05.2010

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 "")
person Community    schedule 04.07.2012

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

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>
person Community    schedule 08.01.2016
comment
<script language=="Javascript"> допустимый синтаксис (не риторический вопрос)? - person Peter Mortensen; 27.05.2021
comment
В чем разница между theEvent.preventDefault и theEvent.preventDefault()? (Используется в той же конструкции) - person Peter Mortensen; 27.05.2021

Вот простой форматировщик на ванильном JavaScript:

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

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

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

    return formattedOutput;
}
person Community    schedule 22.11.2016

Вот мой ...

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;
}
person Community    schedule 19.10.2012
comment
Объяснение было бы в порядке. - person Peter Mortensen; 27.05.2021

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

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("");
}
person Community    schedule 09.09.2014
comment
Объяснение было бы в порядке. Как минимум минимум заявление о том, для какого диапазона чисел он должен работать. Вы также можете включить некоторые образцы входных и выходных данных (например, вы можете использовать некоторые образцы входных данных из других ответов). - person Peter Mortensen; 27.05.2021

Взяв несколько из лучших ответов, я объединил и составил ECMAScript 2015 (ES6), которая передает ESLint.

export const formatMoney = (
  amount,
  decimalCount = 2,
  decimal = '.',
  thousands = ',',
  currencySymbol = '$',
) => {
  if (typeof Intl === 'object') {
    return new Intl.NumberFormat('en-AU', {
      style: 'currency',
      currency: 'AUD',
    }).format(amount);
  }
  // Fallback if Intl is not present.
  try {
    const negativeSign = amount < 0 ? '-' : '';
    const amountNumber = Math.abs(Number(amount) || 0).toFixed(decimalCount);
    const i = parseInt(amountNumber, 10).toString();
    const j = i.length > 3 ? i.length % 3 : 0;
    return (
      currencySymbol +
      negativeSign +
      (j ? i.substr(0, j) + thousands : '') +
      i.substr(j).replace(/(\d{3})(?=\d)/g, `$1${thousands}`) +
      (decimalCount
        ? decimal +
          Math.abs(amountNumber - i)
            .toFixed(decimalCount)
            .slice(2)
        : '')
    );
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error(e);
  }
  return amount;
};
person Community    schedule 04.10.2020

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

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)
)
person Community    schedule 06.04.2015
comment
Объяснение было бы в порядке. Например, какова цель ar[0] | 0? - person Peter Mortensen; 27.05.2021

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

Он форматирует данное числовое значение в формат, специфичный для языка. В данном примере я использовал 'en', в то время как тестировал 'es', 'fr' и другие страны, где формат варьируется . Он не только не позволяет пользователю вводить символы, но и форматирует значение при выводе табуляции.

Я создал компоненты для Числового, а также для Десятичного формата. Помимо этого, я создал функции parseNumber (значение, языковой стандарт) и parseDecimal (значение, языковой стандарт), которые будут анализировать отформатированные данные для любых других бизнес-целей. Указанная функция примет форматированные данные и вернет неформатированное значение. Я использовал плагин валидатора jQuery в приведенном ниже общем коде.

HTML:

<tr>
    <td>
        <label class="control-label">
            Number Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="numberField"
                   name="numberField"
                   class="form-control"
                   autocomplete="off"
                   maxlength="17"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-msg-maxlength="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
                   data-rule-numberExceedsMaxLimit="en"
                   data-msg-numberExceedsMaxLimit="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
                   onkeydown="return isNumber(event, 'en')"
                   onkeyup="return updateField(this)"
                   onblur="numberFormatter(this,
                               'en',
                               'Invalid character(s) found. Please enter valid characters.')">
        </div>
    </td>
</tr>

<tr>
    <td>
        <label class="control-label">
            Decimal Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="decimalField"
                   name="decimalField"
                   class="form-control"
                   autocomplete="off"
                   maxlength="20"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-msg-maxlength="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
                   data-rule-decimalExceedsMaxLimit="en"
                   data-msg-decimalExceedsMaxLimit="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
                   onkeydown="return isDecimal(event, 'en')"
                   onkeyup="return updateField(this)"
                   onblur="decimalFormatter(this,
                       'en',
                       'Invalid character(s) found. Please enter valid characters.')">
        </div>
    </td>
</tr>

JavaScript:

/*
 * @author: dinesh.lomte
 */
/* Holds the maximum limit of digits to be entered in number field. */
var numericMaxLimit = 13;
/* Holds the maximum limit of digits to be entered in decimal field. */
var decimalMaxLimit = 16;

/**
 *
 * @param {type} value
 * @param {type} locale
 * @returns {Boolean}
 */
parseDecimal = function(value, locale) {

    value = value.trim();
    if (isNull(value)) {
        return 0.00;
    }
    if (isNull(locale)) {
        return value;
    }
    if (getNumberFormat(locale)[0] === '.') {
        value = value.replace(/\./g, '');
    } else {
        value = value.replace(
                    new RegExp(getNumberFormat(locale)[0], 'g'), '');
    }
    if (getNumberFormat(locale)[1] === ',') {
        value = value.replace(
                    new RegExp(getNumberFormat(locale)[1], 'g'), '.');
    }
    return value;
};

/**
 *
 * @param {type} element
 * @param {type} locale
 * @param {type} nanMessage
 * @returns {Boolean}
 */
decimalFormatter = function (element, locale, nanMessage) {

    showErrorMessage(element.id, false, null);
    if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
        return true;
    }
    var value = element.value.trim();
    value = value.replace(/\s/g, '');
    value = parseDecimal(value, locale);
    var numberFormatObj = new Intl.NumberFormat(locale,
            {   minimumFractionDigits: 2,
                maximumFractionDigits: 2
            }
    );
    if (numberFormatObj.format(value) === 'NaN') {
        showErrorMessage(element.id, true, nanMessage);
        setFocus(element.id);
        return false;
    }
    element.value = numberFormatObj.format(value);
    return true;
};

/**
 *
 * @param {type} element
 * @param {type} locale
 * @param {type} nanMessage
 * @returns {Boolean}
 */
numberFormatter = function (element, locale, nanMessage) {

    showErrorMessage(element.id, false, null);
    if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
        return true;
    }
    var value = element.value.trim();
    var format = getNumberFormat(locale);
    if (hasDecimal(value, format[1])) {
        showErrorMessage(element.id, true, nanMessage);
        setFocus(element.id);
        return false;
    }
    value = value.replace(/\s/g, '');
    value = parseNumber(value, locale);
    var numberFormatObj = new Intl.NumberFormat(locale,
            {   minimumFractionDigits: 0,
                maximumFractionDigits: 0
            }
    );
    if (numberFormatObj.format(value) === 'NaN') {
        showErrorMessage(element.id, true, nanMessage);
        setFocus(element.id);
        return false;
    }
    element.value =
            numberFormatObj.format(value);
    return true;
};

/**
 *
 * @param {type} id
 * @param {type} flag
 * @param {type} message
 * @returns {undefined}
 */
showErrorMessage = function(id, flag, message) {

    if (flag) {
        // only add if not added
        if ($('#'+id).parent().next('.app-error-message').length === 0) {
            var errorTag = '<div class=\'app-error-message\'>' + message + '</div>';
            $('#'+id).parent().after(errorTag);
        }
    } else {
        // remove it
        $('#'+id).parent().next(".app-error-message").remove();
    }
};

/**
 *
 * @param {type} id
 * @returns
 */
setFocus = function(id) {

    id = id.trim();
    if (isNull(id)) {
        return;
    }
    setTimeout(function() {
        document.getElementById(id).focus();
    }, 10);
};

/**
 *
 * @param {type} value
 * @param {type} locale
 * @returns {Array}
 */
parseNumber = function(value, locale) {

    value = value.trim();
    if (isNull(value)) {
        return 0;
    }
    if (isNull(locale)) {
        return value;
    }
    if (getNumberFormat(locale)[0] === '.') {
        return value.replace(/\./g, '');
    }
    return value.replace(
        new RegExp(getNumberFormat(locale)[0], 'g'), '');
};

/**
 *
 * @param {type} locale
 * @returns {Array}
 */
getNumberFormat = function(locale) {

    var format = [];
    var numberFormatObj = new Intl.NumberFormat(locale,
            {   minimumFractionDigits: 2,
                maximumFractionDigits: 2
            }
    );
    var value = numberFormatObj.format('132617.07');
    format[0] = value.charAt(3);
    format[1] = value.charAt(7);
    return format;
};

/**
 *
 * @param {type} value
 * @param {type} fractionFormat
 * @returns {Boolean}
 */
hasDecimal = function(value, fractionFormat) {

    value = value.trim();
    if (isNull(value) || isNull(fractionFormat)) {
        return false;
    }
    if (value.indexOf(fractionFormat) >= 1) {
        return true;
    }
};

/**
 *
 * @param {type} event
 * @param {type} locale
 * @returns {Boolean}
 */
isNumber = function(event, locale) {

    var keyCode = event.which ? event.which : event.keyCode;
    // Validating if user has pressed shift character
    if (keyCode === 16) {
        return false;
    }
    if (isNumberKey(keyCode)) {
        return true;
    }
    var numberFormatter = [32, 110, 188, 190];
    if (keyCode === 32
            && isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
        return true;
    }
    if (numberFormatter.indexOf(keyCode) >= 0
            && getNumberFormat(locale)[0] === getFormat(keyCode)) {
        return true;
    }
    return false;
};

/**
 *
 * @param {type} event
 * @param {type} locale
 * @returns {Boolean}
 */
isDecimal = function(event, locale) {

    var keyCode = event.which ? event.which : event.keyCode;
    // Validating if user has pressed shift character
    if (keyCode === 16) {
        return false;
    }
    if (isNumberKey(keyCode)) {
        return true;
    }
    var numberFormatter = [32, 110, 188, 190];
    if (keyCode === 32
            && isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
        return true;
    }
    if (numberFormatter.indexOf(keyCode) >= 0
            && (getNumberFormat(locale)[0] === getFormat(keyCode)
                || getNumberFormat(locale)[1] === getFormat(keyCode))) {
        return true;
    }
    return false;
};

/**
 *
 * @param {type} keyCode
 * @returns {Boolean}
 */
isNumberKey = function(keyCode) {

    if ((keyCode >= 48 && keyCode <= 57) ||
        (keyCode >= 96 && keyCode <= 105)) {
        return true;
    }
    var keys = [8, 9, 13, 35, 36, 37, 39, 45, 46, 109, 144, 173, 189];
    if (keys.indexOf(keyCode) !== -1) {
        return true;
    }
    return false;
};

/**
 *
 * @param {type} keyCode
 * @returns {JSON@call;parse.numberFormatter.value|String}
 */
getFormat = function(keyCode) {

    var jsonString = '{"numberFormatter" : [{"key":"32", "value":" ", "description":"space"}, {"key":"188", "value":",", "description":"comma"}, {"key":"190", "value":".", "description":"dot"}, {"key":"110", "value":".", "description":"dot"}]}';
    var jsonObject = JSON.parse(jsonString);
    for (var key in jsonObject.numberFormatter) {
        if (jsonObject.numberFormatter.hasOwnProperty(key)
                && keyCode === parseInt(jsonObject.numberFormatter[key].key)) {
            return jsonObject.numberFormatter[key].value;
        }
    }
    return '';
};

/**
 *
 * @type String
 */
var jsonString = '{"shiftCharacterNumberMap" : [{"char":")", "number":"0"}, {"char":"!", "number":"1"}, {"char":"@", "number":"2"}, {"char":"#", "number":"3"}, {"char":"$", "number":"4"}, {"char":"%", "number":"5"}, {"char":"^", "number":"6"}, {"char":"&", "number":"7"}, {"char":"*", "number":"8"}, {"char":"(", "number":"9"}]}';

/**
 *
 * @param {type} value
 * @returns {JSON@call;parse.shiftCharacterNumberMap.number|String}
 */
getShiftCharSpecificNumber = function(value) {

    var jsonObject = JSON.parse(jsonString);
    for (var key in jsonObject.shiftCharacterNumberMap) {
        if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
                && value === jsonObject.shiftCharacterNumberMap[key].char) {
            return jsonObject.shiftCharacterNumberMap[key].number;
        }
    }
    return '';
};

/**
 *
 * @param {type} value
 * @returns {Boolean}
 */
isShiftSpecificChar = function(value) {

    var jsonObject = JSON.parse(jsonString);
    for (var key in jsonObject.shiftCharacterNumberMap) {
        if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
                && value === jsonObject.shiftCharacterNumberMap[key].char) {
            return true;
        }
    }
    return false;
};

/**
 *
 * @param {type} element
 * @returns {undefined}
 */
updateField = function(element) {

    var value = element.value;

    for (var index = 0; index < value.length; index++) {
        if (!isShiftSpecificChar(value.charAt(index))) {
            continue;
        }
        element.value = value.replace(
                value.charAt(index),
                getShiftCharSpecificNumber(value.charAt(index)));
    }
};

/**
 *
 * @param {type} value
 * @param {type} element
 * @param {type} params
 */
jQuery.validator.addMethod('numberExceedsMaxLimit', function(value, element, params) {

    value = parseInt(parseNumber(value, params));
    if (value.toString().length > numericMaxLimit) {
        showErrorMessage(element.id, false, null);
        setFocus(element.id);
        return false;
    }
    return true;
}, 'Exceeding the maximum limit of 13 digits. Example: 1234567890123.');

/**
 *
 * @param {type} value
 * @param {type} element
 * @param {type} params
 */
jQuery.validator.addMethod('decimalExceedsMaxLimit', function(value, element, params) {

    value = parseFloat(parseDecimal(value, params)).toFixed(2);
    if (value.toString().substring(
            0, value.toString().lastIndexOf('.')).length > numericMaxLimit
            || value.toString().length > decimalMaxLimit) {
        showErrorMessage(element.id, false, null);
        setFocus(element.id);
        return false;
    }
    return true;
}, 'Exceeding the maximum limit of 16 digits. Example: 1234567890123.00.');

/**
 * @param {type} id
 * @param {type} locale
 * @returns {boolean}
 */
isNumberExceedMaxLimit = function(id, locale) {

    var value = parseInt(parseNumber(
            document.getElementById(id).value, locale));
    if (value.toString().length > numericMaxLimit) {
        setFocus(id);
        return true;
    }
    return false;
};

/**
 * @param {type} id
 * @param {type} locale
 * @returns {boolean}
 */
isDecimalExceedsMaxLimit = function(id, locale) {

    var value = parseFloat(parseDecimal(
            document.getElementById(id).value, locale)).toFixed(2);
    if (value.toString().substring(
            0, value.toString().lastIndexOf('.')).length > numericMaxLimit
            || value.toString().length > decimalMaxLimit) {
        setFocus(id);
        return true;
    }
    return false;
};
person Community    schedule 30.08.2019

Крошечная библиотека JavaScript с нулевой зависимостью (1 Кбайт) от CurrencyRate.today, обеспечивающая простой способ и расширенное форматирование чисел, денег и валюты, удаляет все форматирование / мусор и возвращает необработанное значение с плавающей запятой.

https://github.com/dejurin/format-money-js

npm install format-money-js

Функции:

  • from: форматирование денег и валюты;

  • un: удаляет все форматирование / беспорядок и возвращает необработанное значение с плавающей запятой.

Примеры 1

const { FormatMoney } = require('format-money-js');

const fm = new FormatMoney({
  decimals: 2
});

console.log(fm.from(12345.67, { symbol: '$' })); // return string: $12,345.67
console.log(fm.un('€12,345;67')); // return number: 12345.67

Пример 2

const { FormatMoney } = require('format-money-js');

const fm = new FormatMoney({
  decimals: 2
});

console.log(fm.from(
  12345.67, 
  { symbol: '$' },
  true // Parse, return object
  )
);
/* return object: 
{
  source: 12345.67,
  negative: false,
  fullAmount: '12,345.67',
  amount: '12,345',
  decimals: '.67',
  symbol: '$'
}*/
person Community    schedule 14.07.2021

Вот быстрый способ использования regexp и replace.

function formatCurrency(number, dp, ts) {
  var num = parseFloat(number); // Convert to float
  var pw; // For Internet Explorer
  dp = parseInt(dp, 10); // Decimal point
  dp = isNaN(dp) ? 2 : dp; // Default 2 decimal point
  ts = ts || ','; // Thousands separator

  return num != number ?
    false : // Return false for NaN
    ((0.9).toFixed(0) == '1' ? // For cater Internet Explorer toFixed bug
        num.toFixed(dp) : // Format to fix n decimal point with round up
        (Math.round(num * (pw = Math.pow(10, dp) || 1)) / pw).toFixed(dp) // For fixing Internet Explorer toFixed bug on round up value like 0.9 in toFixed
    ).replace(/^(-?\d{1,3})((\d{3})*)(\.\d+)?$/, function(all, first, subsequence, dmp, dec) { // Separate string into different parts
      return (first || '') + subsequence.replace(/(\d{3})/g, ts + '$1') + (dec || ''); // Add thousands separator and rejoin all parts
    } );
}
person Community    schedule 22.07.2011
comment
приведите пример использования этой функции. - person jao; 16.11.2012

person    schedule
comment
Объяснение было бы в порядке. Например, как это может быть так просто и не охвачено ни одним из предыдущих более чем 50 ответов за 9 лет (в то время)? - person Peter Mortensen; 27.05.2021

person    schedule
comment
Объяснение было бы в порядке. - person Peter Mortensen; 27.05.2021