Jak sformatować liczby jako ciąg waluty?

1844

Chciałbym sformatować cenę w JavaScript. Chciałbym funkcji, która przyjmuje floatjako argument i zwraca stringsformatowane w ten sposób:

"$ 2,500.00"

Jak najlepiej to zrobić?

Daniel Magliola
źródło
8
W formatNumberjavascript nie ma wbudowanej funkcji
zerkms
500
Wszystkim, którzy czytają to w przyszłości, proszę nie używać float do przechowywania waluty. Utracisz precyzję i dane. Powinieneś zapisać go jako całkowitą liczbę centów (lub groszy itp.), A następnie przekonwertować przed wyjściem.
Philip Whitehouse
8
@ user1308743 Float nie przechowuje miejsc dziesiętnych. Przechowuje liczby przy użyciu wartości, podstawy i przesunięcia. 0,01 nie jest w rzeczywistości reprezentowalny. Zobacz: en.wikipedia.org/wiki/Floating_point#Accuracy_problems
Philip Whitehouse
6
@ user1308743: Wyobraź sobie, że reprezentujesz bardzo dużą liczbę (powiedzmy, że jesteś szczęściarzem i jest to saldo konta bankowego). Czy naprawdę chcesz stracić pieniądze z powodu braku precyzji?
ereOn
163
Dlaczego więc nikt nie zasugerował: (2500) .toLocaleString („en-GB”, {style: „currency”, currency: „GBP”, minimumFractionDigits: 2}) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nick Grealy,

Odpowiedzi:

1791

Number.prototype.toFixed

To rozwiązanie jest kompatybilne z każdą główną przeglądarką:

  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)

Wystarczy dodać symbol waluty (np. "$" + profits.toFixed(2)), A otrzymasz kwotę w dolarach.

Funkcja niestandardowa

Jeśli potrzebujesz użyć ,między każdą cyfrą, możesz użyć tej funkcji:

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>

Używaj go w ten sposób:

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

Jeśli zawsze będziesz używać „.” i „,” możesz pominąć ich wywołanie metody, a metoda domyślnie je dla ciebie.

(123456789.12345).formatMoney(2);

Jeśli w twojej kulturze dwa symbole są odwrócone (tj. Europejczycy) i chcesz użyć wartości domyślnych, po prostu wklej następujące dwie linie w formatMoneymetodzie:

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

Funkcja niestandardowa (ES6)

Jeśli możesz użyć nowoczesnej składni ECMAScript (tj. Poprzez Babel), możesz zamiast tego użyć tej prostszej funkcji:

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>

haykam
źródło
26
przede wszystkim doskonały, zwięzły kod. Jednakże, jeśli jesteś amerykański, należy zmienić domyślnych di tbyć .i ,odpowiednio tak, że nie trzeba określać je za każdym razem. Ponadto zalecam zmodyfikowanie początku returninstrukcji tak, aby brzmiała: return s + '$' + [rest]w przeciwnym razie nie otrzymasz znaku dolara.
Jason
744
Nie jestem pewien, dlaczego ludzie myślą, że ten kod jest piękny. To jest nieczytelne. Wygląda na to, że działa dobrze, ale nie jest piękny.
usr
86
Czy funkcja formatMoney została gdzieś skopiowana z jakiegoś zminimalizowanego kodu JavaScript? Nie możesz opublikować oryginału? Co oznaczają zmienne c, d, i, j, n, s oraz t? Sądząc po liczbie głosów pozytywnych i komentarzy w tym poście, mogę założyć, że ten kod został wklejony wszędzie na stronach produkcyjnych ... Powodzenia w utrzymywaniu kodu, jeśli pewnego dnia wystąpi błąd!
zuallauz,
259
"poezja"? Bardziej jak zaciemnienie. To nie jest kod golfowy; użyj małej białej przestrzeni. Właściwe nazwy zmiennych również nie zaszkodzą.
keithjgrant
1511

Intl.numberformat

JavaScript ma formatator liczb (część interfejsu API internacjonalizacji).

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

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

Skrzypce JS

Użyj undefinedzamiast pierwszego argumentu ( 'en-US'w tym przykładzie), aby użyć ustawień regionalnych systemu (ustawień narodowych użytkownika w przypadku, gdy kod działa w przeglądarce). Dalsze objaśnienie kodu regionalnego .

Oto lista kodów walut .

Intl.NumberFormat vs Number.prototype.toLocaleString

Ostatnia uwaga porównująca to do starszych. toLocaleString. Oba oferują zasadniczo tę samą funkcjonalność. Jednak toLocaleString w swoich starszych inkarnacjach (pre-Intl) tak naprawdę nie obsługuje ustawień regionalnych : używa ustawień regionalnych systemu. Dlatego upewnij się, że używasz poprawnej wersji ( MDN sugeruje sprawdzenie istnieniaIntl ). Również wydajność obu jest taka sama dla jednego elementu, ale jeśli masz wiele liczb do sformatowania, użycie Intl.NumberFormatjest ~ 70 razy szybsze. Oto jak używać toLocaleString:

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

Kilka uwag na temat obsługi przeglądarki

  • Obsługa przeglądarek nie stanowi już problemu - 97,5% wsparcia na całym świecie, 98% w USA i 99% w UE
  • Jest pewien podkład, aby go obsługiwać w skamieniałych przeglądarkach (takich jak IE8), jeśli naprawdę potrzebujesz
  • Więcej informacji znajdziesz w CanIUse
aross
źródło
89
To idomatyczne JavaScript, proste i eleganckie rozwiązanie jest dokładnie tym, czego szukałem.
Guilhem Soulas
9
Głosowanie na tę, ponieważ jest to głupia prosta odpowiedź, która działa natywnie.
Trasiva
17
Jestem pewien, że dość wysoki odsetek przeglądarek obsługuje to teraz. To powinno być oceniane znacznie więcej.
flq
2
To świetna odpowiedź i mam do czynienia z dynamiczną wartością waluty, więc jeśli używasz w Europie, to zmienia się na EUR i pokazuje znak euro. Działa uczta!
Sprose,
3
Jest rok 2018 i jest to w zasadzie obsługiwane wszędzie. To powinna być poprawna odpowiedź.
sarink
1340

Krótkie i szybkie rozwiązanie (działa wszędzie!)

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

Ideą tego rozwiązania jest zastąpienie dopasowanych sekcji pierwszym dopasowaniem i przecinkiem, tj '$&,' . Dopasowywanie odbywa się przy użyciu metody lookahead . Możesz odczytać wyrażenie „dopasuj liczbę, jeśli następuje po niej ciąg trzech zestawów liczb (jeden lub więcej) i kropka” .

TESTY:

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"

PRÓBNY: http://jsfiddle.net/hAfMM/9571/


Rozszerzone krótkie rozwiązanie

Możesz także rozszerzyć prototyp Numberobiektu, aby dodać dodatkowe wsparcie dla dowolnej liczby miejsc po przecinku [0 .. n]i wielkości grup liczb[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"

DEMO / TESTY: http://jsfiddle.net/hAfMM/435/


Super rozszerzone krótkie rozwiązanie

W tej super rozszerzonej wersji możesz ustawić różne typy ograniczników:

/**
 * 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"

DEMO / TESTY: http://jsfiddle.net/hAfMM/612/

VisioN
źródło
21
I rzeczywiście poszedł o krok dalej: .replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,").
kalisjoshua
4
Wersja CoffeeScript z wyrażeniami regularnymi VisioN i kalisjoshua oraz sposób określania miejsca po przecinku (możesz więc pozostawić domyślną wartość 2 lub podać 0 dla braku po przecinku): Number.prototype.toMoney = (decimal=2) -> @toFixed(decimal).replace /(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,"
Eric Anderson
11
@Abbas Tak, wymienić \.z $(koniec linii), tj this.toFixed(0).replace(/(\d)(?=(\d{3})+$)/g, "$1,").
VisioN
2
@hanumant Gramatyka regularna jest tutaj nieco skomplikowana, dlatego sugeruję najpierw przeczytać podręczniki dotyczące wyrażeń regularnych (np. w MDN ). Ideą jest zastąpienie dopasowanych sekcji pierwszym dopasowaniem i przecinkiem, tj $1,. Dopasowywanie odbywa się przy użyciu metody lookahead . Możesz odczytać wyrażenie „dopasuj liczbę, jeśli następuje po niej ciąg trzech zestawów liczb (jeden lub więcej) i kropka” .
VisioN
2
@ JuliendePrabère Podaj przykład długiej liczby, która nie działa z tym podejściem.
VisioN
248

Spójrz na obiekt JavaScript Number i sprawdź, czy może ci pomóc.

  • toLocaleString() sformatuje liczbę przy użyciu separatora tysięcy określonego dla lokalizacji.
  • toFixed() zaokrągli liczbę do określonej liczby miejsc po przecinku.

Aby użyć ich w tym samym czasie, wartość musi zostać zmieniona z powrotem na liczbę, ponieważ oba generują ciąg.

Przykład:

Number((someNumber).toFixed(1)).toLocaleString()
17 z 26
źródło
2
Dzięki! Na podstawie tego pomysłu udało mi się stworzyć taki, który jest krótki i prosty! (i zlokalizowany) Doskonały.
Daniel Magliola
7
Właściwie możesz. tj. dla dolarów: „$” + (wartość + 0,001) .toLocaleString (). slice (0, -1)
Zaptree,
6
Wygląda na to, że byłoby świetnie, ale obecnie obsługa przeglądarek jest niewielka
acorncom
1
@acorncom Dlaczego mówisz, że istnieje „mała obsługa przeglądarki”? Obiekt Number istnieje od JavaScript 1.1. Podaj numer referencyjny, który poprze twoje roszczenie.
Doug S
2
Należy zachować ostrożność, ponieważ istnieje stara wersja toLocaleStringużywająca ustawień regionalnych systemu i nowa (niekompatybilna) pochodząca z interfejsu API ECMAScript Intl. Wyjaśniono tutaj . Ta odpowiedź wydaje się być przeznaczona dla starej wersji.
aross
162

Poniżej znajduje się kod Patricka Desjardinsa (pseudonim Daok) z dodanymi uwagami i drobnymi zmianami:

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

   /*
   according to [/programming/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) : ''); 
}

a tutaj kilka testów:

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

Niewielkie zmiany to:

  1. przeniósł trochę Math.abs(decimals)do zrobienia tylko wtedy, gdy nie jest NaN.

  2. decimal_sep nie może być już pustym ciągiem (pewnego rodzaju separatorem dziesiętnym jest MUSI)

  3. używamy typeof thousands_sep === 'undefined'zgodnie z sugestią w Jak najlepiej ustalić, czy argument nie jest wysyłany do funkcji JavaScript

  4. (+n || 0)nie jest potrzebny, ponieważ thisjest Numberobiektem

JS Fiddle

Marco Demaio
źródło
8
Możesz użyć „10” jako podstawy w parsowaniu. W przeciwnym razie dowolna liczba rozpoczynająca się od „0” użyje numeracji ósemkowej.
sohtimsso1970,
3
@ sohtimsso1970: przepraszam za spóźnioną odpowiedź, ale czy mógłbyś wyjaśnić coś więcej? Nie widzę, gdzie liczbę można interpretować jako liczbę ósemkową. Wywoływana parseIntjest wartość bezwzględna części INTEGER liczby. Część INTEGER nie może zaczynać się od ZERO, chyba że jest to po prostu ZERO! I parseInt(0) === 0ósemkowy lub dziesiętny.
Marco Demaio,
spróbuj na przykład: parseInt („016”) ... zwraca 14, ponieważ parseInt zakłada, że ​​jest zakodowany ósemkowo, gdy łańcuch zaczyna się od zera.
Tracker1
4
@ Tracker1: Zrozumiałem, że liczba zaczynająca się od 0jest uważana za ósemkową parseInt. Ale w tym kodzie NIE MOŻNA parseIntodbierać 016jako danych wejściowych (lub jakiejkolwiek innej wartości sformatowanej ósemkowo), ponieważ przekazywany argument parseIntjest przetwarzany przez Math.absfunkcję. Nie ma więc możliwości parseIntotrzymania liczby zaczynającej się od zera, chyba że jest to tylko zero lub 0.nn(gdzie nnsą miejsca po przecinku). Ale zarówno łańcuchy, jak 0i 0.nnłańcuchy zostałyby przekonwertowane parseIntna zwykłą ZERO, jak się przypuszcza.
Marco Demaio,
Ta funkcja jest niepoprawna:> (2030) .toMoney (0, '.', ''); <„2 03 0”
Anton P. Robul
124

account.js to niewielka biblioteka JavaScript do formatowania liczb, pieniędzy i walut.

GasheK
źródło
... pamiętaj tylko o przekazaniu symbolu waluty, w przeciwnym razie wystąpi błąd w IE7 i IE8, IE9 jest w każdym razie w porządku
wektor
2
Wygląda na to, że błąd IE7 / IE8 został naprawiony.
Mat Schaffer,
2
To świetna biblioteka, możliwość przekazania symbolu waluty jest również dobrym pomysłem, ponieważ wszystkie szczegóły waluty są zawarte w wywołaniu / ustawieniach jednej funkcji
farinspace
2
Podoba mi się to, że można zrobić odwrotnie - przekazać sformatowany ciąg waluty i uzyskać wartość liczbową.
Neil Monroe
2
Accounting.js nie wydaje się ostatnio utrzymywany. Jednym z rozwidleń ostatnich zmian jest github.com/nashdot/accounting-js
RationalDev lubi GoFundMonica
124

Jeśli kwota jest liczbą, powiedzmy -123, to

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

wyprodukuje ciąg "-$123.00" .

Oto kompletny przykład działania .

cs01
źródło
7
Ta odpowiedź była już prawie dla mnie, ale potrzebowałem ją zaokrąglić do najbliższego grosza. Właśnie tego użyłem kwota.toLocaleString („en-GB”, {style: „currency”, currency: „GBP”, maximumFractionDigits: 2});
Nico,
Powyższy kod zaokrągla liczbę wymaganych cyfr. Zobacz przykład i wpisz 1,237 w polu wprowadzania.
Daniel Barbalace
3
Wydaje się, że nie działa w Safari. Zwraca tylko liczbę jako ciąg bez formatowania.
Lance Anderson
1
Wow, to naprawdę świetna odpowiedź. Powinien być na górze.
Ethan
2
Jeśli z jakiegoś powodu nie chcesz centów, możesz zmienić dokładność dziesiętną za pomocą:minimumFractionDigits: 0
Horacio
99

Oto najlepszy formatyzator pieniędzy js, jaki widziałem:

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

Został ponownie sformatowany i zapożyczony stąd: https://stackoverflow.com/a/149099/751484

Będziesz musiał podać swój własny oznacznik waluty (użyłeś $ powyżej).

Nazwij to w ten sposób (chociaż pamiętaj, że domyślnie argumenty to 2, przecinek i kropka, więc nie musisz podawać żadnych argumentów, jeśli taka jest twoja preferencja):

var myMoney=3543.75873;
var formattedMoney = '$' + myMoney.formatMoney(2,',','.'); // "$3,543.76"
Jonathan M.
źródło
uważaj na znak globals, i, j
hacklikecrack
6
@hacklikecrack, wszystkie zmienne są lokalne; są w varoświadczeniu.
Jonathan M
3
przepraszam, tak, choć ponownie redagujesz argumenty. Wcięcie! ;)
hacklikecrack
Okropne użycie nazw zmiennych!
Serj Sagan,
77

Tutaj są już świetne odpowiedzi. Oto kolejna próba, dla zabawy:

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

I niektóre testy:

formatDollar(45664544.23423) // "$45,664,544.23"
formatDollar(45) // "$45.00"
formatDollar(123) // "$123.00"
formatDollar(7824) // "$7,824.00"
formatDollar(1) // "$1.00"

Edytowane: teraz będzie również obsługiwać liczby ujemne

Wayne Burkett
źródło
poezja. znakomity. czy próbowałeś zmniejszyćRight () developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…, co powinno wyeliminować reverse ()?
Steve
1
@ Steve - Masz rację, ale musisz zrobić coś takiego jak i = orig.length - i - 1oddzwanianie. Mimo to o jeden krok mniej w tablicy.
Wayne,
11
Nie chodzi o kompatybilność: reduceMetoda została wprowadzona w Ecmascript 1.8 i nie jest obsługiwana w Internet Explorerze 8 i niższych.
Blaise
Jak powiedział @Blaise, ta metoda nie będzie działać w IE 8 lub niższej.
rsbarro
Tak, to oczywiście prawda. Jak zaznaczono w samej odpowiedzi, jest to tylko dla zabawy. Ponadto powinien dobrze radzić sobie z liczbami ujemnymi.
Wayne
76

Działa dla wszystkich obecnych przeglądarek

Służy toLocaleStringdo formatowania waluty w jej reprezentacji wrażliwej na język (przy użyciu kodów walut ISO 4217 ).

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

Przykładowe fragmenty kodu Rand południowoafrykańskiego dla @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

Nick Grealy
źródło
1
Ponieważ argumenty „ustawienia regionalne” i „opcje” są obsługiwane tylko przez bardzo małą liczbę przeglądarek, takich jak Chrome 24, IE11 i Opera 15. Firefox, Safari i starsze wersje innych nadal go nie obsługują.
VisioN
3
Uzgodniony, nie jest jeszcze w pełni obsługiwany we wszystkich przeglądarkach (jeszcze), ale nadal jest rozwiązaniem. (I prawdopodobnie najbardziej ważne rozwiązanie, ponieważ jego naprzód kompatybilne z przeglądarkami nieobsługiwanych i jest to udokumentowane cechą JavaScript API.)
Nick Grealy
1
Podoba mi się to i cieszę się, że działa z grupowaniem cyfr indyjskich.
MSC
7
Jest to w pełni obsługiwane od 2017 r. I powinna być jedyną prawidłową odpowiedzią
Evgeny
1
Najnowsze i najlepsze :) FF69, Chrome76 itp. „R 2 500,00” nie jest tym, czego używamy tutaj, powinien być „R 2500,00”, tak samo jak en-GB.
avenmore
70

Myślę, że chcesz f.nettotal.value = "$" + showValue.toFixed(2);

zmiażdżyć
źródło
@ zniszczyć to działa, ale nie przenosi już obliczeń na pole podatkowe?
Rocco The Taco,
11
Po dodaniu do niej znaku $ nie jest to już liczba, lecz ciąg znaków.
zmiażdżyć
Ta opcja nie umieszcza przecinka między tysiącami. :-(
Simon East,
29

Numeral.js - biblioteka js do łatwego formatowania liczb przez @adamwdraper

numeral(23456.789).format('$0,0.00'); // = "$23,456.79"
Yarin
źródło
Widelec Numbro wydaje się zyskać więcej miłości, gdy Numeral.js wydaje się porzucony: github.com/foretagsplatsen/numbro
RationalDev lubi GoFundMonica
Numeral.js jest znów aktywny.
adamwdraper
27

Ok, na podstawie tego, co powiedziałeś, używam tego:

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;

Jestem otwarty na propozycje ulepszeń (wolę nie uwzględniać YUI tylko po to :-)) Wiem już, że powinienem wykrywać „.” zamiast po prostu używać go jako separatora dziesiętnego ...

Daniel Magliola
źródło
8
Pamiętaj, że twoja wersja nie zaokrągla poprawnie do dwóch cyfr dziesiętnych. Na przykład 3,706 byłoby sformatowane jako „3,70 £”, a nie „3,71 £”, jak powinno być.
Ates Goral
Tak, w moim przypadku jest to w porządku, ponieważ kwoty, z którymi pracuję, mają już co najwyżej 2 cyfry. Powodem, dla którego muszę
ustawić
26

Korzystam z biblioteki Globalize (od Microsoft):

To świetny projekt do lokalizowania liczb, walut i dat oraz automatycznego formatowania ich zgodnie z ustawieniami użytkownika! ... i pomimo tego, że powinno to być rozszerzenie jQuery, jest to obecnie w 100% niezależna biblioteka. Proponuję wam wszystkim wypróbować! :)

daveoncode
źródło
3
Wow, dlaczego nie jest to już bardziej doceniane? Duża ustandaryzowana biblioteka do wszelkiego rodzaju formatowania. Standardowe parametry formatowania z prawidłową globalizacją. Świetna odpowiedź!!
pbarranis,
Nadal jest uważany za etap alfa, więc używaj go ostrożnie, ale świetne znalezisko.
Neil Monroe
1
Już nie w wersji alfa (lub beta). Wydaje się to bardzo przydatne, gdy czekamy, aż Safari spełni nowy standard i umrze IE <11.
Guy Schalnat,
25

javascript-number-formatter (wcześniej w Google Code )

  • Krótki, szybki, elastyczny, ale samodzielny. Tylko 75 wierszy, w tym informacje o licencji MIT, puste wiersze i komentarze.
  • Zaakceptuj standardowe formatowanie liczb, takie jak #,##0.00lub z negacją -000.####.
  • Zebrane dowolny format kraj jak # ##0,00, #,###.##, #'###.##lub dowolnego typu non-numeracji symbolem.
  • Zaakceptuj dowolną liczbę grup cyfr. #,##,#0.000lub #,###0.##wszystkie są ważne.
  • Zaakceptuj wszelkie nadmiarowe / niezawodne formatowanie. ##,###,##.#lub 0#,#00#.###0#wszystko w porządku.
  • Automatyczne zaokrąglanie liczb.
  • Prosty interfejs, tylko maska dostaw i wartości tak: format( "0.0000", 3.141592).
  • Dołącz prefiks i sufiks do maski

(fragment z README)

Goodeq
źródło
23

+1 Jonathanowi M. za dostarczenie oryginalnej metody. Ponieważ jest to jawnie formatator walut, poszedłem dalej i dodałem symbol waluty (domyślnie „$”) do danych wyjściowych i dodałem domyślny przecinek jako separator tysięcy. Jeśli tak naprawdę nie chcesz symbolu waluty (lub separatora tysięcy), po prostu użyj argumentu „” (pusty ciąg) jako argumentu.

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) : "");
};
XML
źródło
Pierwszy var jest trochę dziwny, ponieważ zmienne te są już zadeklarowane w deklaracji funkcji. Poza tym, dzięki!
Rich Bradshaw
2
Masz rację. To błąd, który przyniosłem z oryginału Jonathana M., gdzie wszystkie są powiązane łańcuchem jako jedno wyrażenie var. To powinny być proste zadania. Ustalenie.
XML
Jeśli o to chodzi, myślę, że jest to prawdopodobnie przedwcześnie zoptymalizowane i powinno zostać ponownie przeanalizowane pod kątem czytelności. Ale moim celem było rozszerzenie kodu OP, a nie jego zasadnicza zmiana.
XML
Nie jest tak źle - +n || 0to jedyna rzecz, która wydaje mi się nieco dziwna (w każdym razie dla mnie).
Rich Bradshaw
2
thisto doskonale przydatna nazwa zmiennej. Przekształcenie go w celu nzapisania 3 znaków w czasie definicji mogło być konieczne w erze, w której RAM i przepustowość były liczone w KB, ale jest jedynie zaciemniające w erze, w której minimalizator zajmie się tym wszystkim, zanim dotrze do produkcji. Inne sprytne mikrooptymalizacje są przynajmniej dyskusyjne.
XML
22

Istnieje port javascript funkcji PHP „number_format”.

Uważam, że jest bardzo przydatny, ponieważ jest łatwy w użyciu i rozpoznawalny dla programistów PHP.

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

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

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

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

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

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

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

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

(Blok komentarza do oryginału , zamieszczony poniżej w celu uzyskania przykładów i zaliczek w odpowiednim czasie)

// 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'
DaMayan
źródło
To tylko jedna poprawna funkcja:> liczba_format (2030, 0, '.', '') <'2 030' Świetnie! Dzięki
Anton P. Robul,
21

Krótsza metoda (do wstawiania spacji, przecinka lub punktu) z wyrażeniem regularnym?

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

    n=12345678.9;
    alert(n.toCurrencyString());
rev Julien de Prabère
źródło
20

Nie widziałem czegoś takiego. Jest dość zwięzły i łatwy do zrozumienia.

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

Oto wersja z większą ilością opcji na końcowym wyjściu, umożliwiającą formatowanie różnych walut w różnych formatach lokalizacyjnych.

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

synthet1c
źródło
Świetny fragment kodu, dziękuję. Należy jednak zachować ostrożność, ponieważ nie będzie działać w IE, ponieważ parametry domyślne nie są obsługiwane, a „const” i „let” nie są obsługiwane w <IE11. Użyj tego do naprawy: + moneyFormat: function (price, sign) {+ if (! Sign) sign = '$'; + sztuk = parseFloat (cena) .toFixed (2) .split ('') + var ii = sztuk. długość - 3
Charlie Dalsass
Bez obaw @CharlieDalsass. Polecam użycie babel do skompilowania go do ES5 dla kodu produkcyjnego.
synthet1c
Ale jak zrobić walutę euro? 1.000,00 Euro?
@YumYumYum Dodałem pełny przykład z większą liczbą opcji formatowania, aby umożliwić większą elastyczność.
synthet1c
18

Odpowiedź Patricka Desjardinsa wygląda dobrze, ale wolę mój javascript prosty. Oto funkcja, którą właśnie napisałem, aby pobrać liczbę i zwrócić ją w formacie walutowym (minus znak dolara)

// 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];
}
Tim Saylor
źródło
Potrzebowałem czegoś do pracy zarówno w przeglądarce, jak i w starej wersji Node. To działało idealnie. Dzięki
n8jadams,
17

Główną częścią jest wstawienie separatorów tysiąca, które można wykonać w następujący sposób:

<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)));">
ryku
źródło
Podczas wprowadzania wartości ujemnych do ins1000Sep () otrzymuję błędną liczbę wyjściową.
Peter,
16

Jest wbudowany w function toFixed wjavascript

var num = new Number(349);
document.write("$" + num.toFixed(2));
Brama
źródło
Ta odpowiedź wydaje się zbędna. Odpowiedź Crusha jest już mentinotoFixed()
Ian Dunn
3
toFixed()jest funkcją Numberobiektu i nie działałby, var numgdyby był String, więc dodatkowy kontekst pomógł mi.
timborden
15
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;
}

Od WillMaster .

Bill jaszczurka
źródło
Mały i prosty. Dziękuję Ci.
Connor Simpson
1
proste, ale bez przecinka za 1000
aron
15

Sugeruję klasę NumberFormat z interfejsu API Google Visualization .

Możesz zrobić coś takiego:

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

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

Mam nadzieję, że to pomoże.

juanchopx2
źródło
14

To może być trochę za późno, ale oto metoda, którą właśnie opracowałem dla współpracownika, aby dodać funkcję rozpoznawania ustawień regionalnych .toCurrencyString()do wszystkich liczb. Internalizacja służy wyłącznie do grupowania liczb, a NIE znaku waluty - jeśli wyprowadzasz dolary, użyj tego, "$"co podano, ponieważ $123 4567w Japonii lub Chinach jest tyle samo dolarów, co $1,234,567w USA. Jeśli wypisujesz euro / itp., Zmień znak waluty z "$".

Zadeklaruj to w dowolnym miejscu w SZEFIE lub tam, gdzie to konieczne, tuż przed użyciem:

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

To koniec! Użyj (number).toCurrencyString()wszędzie tam, gdzie chcesz podać liczbę jako walutę.

var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
Jay Dansand
źródło
12

Jak zwykle istnieje wiele sposobów na zrobienie tego samego, ale unikałbym używania, Number.prototype.toLocaleStringponieważ może zwrócić różne wartości w zależności od ustawień użytkownika.

Nie polecam także rozszerzania Number.prototype- rozszerzanie prototypów obiektów natywnych jest złą praktyką, ponieważ może powodować konflikty z kodem innych osób (np. Bibliotek / frameworków / wtyczek) i może nie być kompatybilne z przyszłymi implementacjami / wersjami JavaScript.

Uważam, że Wyrażenia regularne są najlepszym podejściem do problemu, oto moja implementacja:

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

edytowany 30.08.2010: dodano opcję ustawiania liczby cyfr dziesiętnych. edytowany w dniu 2011/08/23: dodano opcję ustawienia liczby cyfr dziesiętnych na zero.

Miller Medeiros
źródło
Chodzi o to, że toLocaleString dostosowuje się do ustawień użytkownika.
Joseph Lennox
11

Oto niektóre rozwiązania, wszystkie przeszły pakiet testowy, pakiet testowy i test porównawczy, jeśli chcesz skopiować i wkleić w celu przetestowania, wypróbuj This Gist .

Metoda 0 (RegExp)

Oprzyj na https://stackoverflow.com/a/14428340/1877620 , ale popraw, jeśli nie ma kropki dziesiętnej.

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

Metoda 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('.');
    };
}

Metoda 2 (Podziel na macierz)

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

Metoda 3 (pętla)

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

Przykład użycia

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

Separator

Jeśli chcemy niestandardowego separatora tysięcy lub separatora dziesiętnego, użyj replace():

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

Zestaw testowy

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

Reper

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

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

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

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
Steely Wing
źródło
Ulepszony z twojej metody 2. zmiana z var a = this.toFixed (precyzja) .split ('.'), Na var mnożnik = Math.pow (10, precyzja + 1), wholeNumber = Math.floor (ten * mnożnik) ; var a = Math.round (wholeNumber / 10) * 10 / multiplikator; if (String (a) .indexOf ('.') <1) {a + = '.00'; } a = String (a) .split ('.'), Nie używaj toFixed, ponieważ jest wadliwy.
vee
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 wszystkie wartości dziesiętne tych wartości powinny wynosić 0,84, a nie 0,83
vee
10

Prosta opcja dla prawidłowego umieszczania przecinków poprzez odwrócenie pierwszego łańcucha i podstawowe wyrażenie regularne.

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();
};
troy
źródło
10

Znalazłem to z: account.js . Jest to bardzo łatwe i idealnie pasuje do moich potrzeb.

// 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€ 

Faysal Haque
źródło
$('#price').val( accounting.formatMoney(OOA, { symbol: "€", precision: 2,thousand: ".", decimal :",",format: "%v%s" } ) );- pokaż 1.000,00 E