Working with currency in JavaScript

Arnaud Dostes
3 min readSep 13, 2019

--

Working with currencies in JavaScript can be more complicated than it seems.

The first issue we have is that a monetary amount is usually represented using a float, so multiplying and dividing them can be tricky. Just try typing 10 / 3 or 3.33 * 3 in a JavaScript console.

Sometimes we need to use whole amounts, but more often than not we’ll be dealing with 2 or possibly more decimals, and for trading and crypto it’s not uncommon to use 4, 6 or even 8 decimals.

So the problem we have to solve is how to multiply and divide real numbers. One solution to this problem is to multiply the real number by 10 until it’s no longer a real number. Instead of multiplying 3.3 by 3, we can multiply 33 by 3, and then divide the result by 10. Here’s one possible implementation:

Dividing is very similar, we can reuse the multiplyMoney function by multiplying by the inverse of what we want to divide by. We then can use the same technique to calculate the remainder.

console.log(3.111 * 2.1); // 6.533100000000001
console.log(multiplyMoney(3.111, 2.1, 6)); // 6.5331
console.log(multiplyMoney(3.111, 2.1)); // 6.53
console.log(10 / 3); // 3.3333333333333335
console.log(divideMoney(10, 3)); // [ 3.33, 0.01 ]
console.log(divideMoney(10, 3, 0)); // [ 3, 1 ]
console.log(divideMoney(10, 3, 1)); // [ 3.3, 0.1 ]

To represent monetary amounts, long gone are the days where a currency symbol needed to be appended to a string. If you’re doing that, stop and use the Intl.NumberFormat api instead. Just choose a locale and a currency and call it a day.

The locale indicates how numbers are represented in a certain language. Some languages use decimals for thousands separators and a period for the decimal separator, some languages it’s the other way around:

  • US English: 1,000,000.5
  • French: 1 000,5
  • Indian number system: 1,00,00,000.5

The currency indicates what symbol to use, and by default uses non significant decimals if it is the norm.

let number = 1000000.5;
let options = { style: 'currency', currency: 'USD' };
console.log(new Intl.NumberFormat('en-US', options).format(number));
// $1,000,000.50
console.log(new Intl.NumberFormat('fr-FR', options).format(number));
// 1 000 000,50 $US
console.log(new Intl.NumberFormat('in-IN', options).format(number));
// US$1.000.000,50
options = { style: 'currency', currency: 'EUR' };
console.log(new Intl.NumberFormat('en-US', options).format(number));
// €1,000,000.50
console.log(new Intl.NumberFormat('fr-FR', options).format(number));
// 1 000 000,50 €
console.log(new Intl.NumberFormat('in-IN', options).format(number));
// €1.000.000,50

The options allow to make a few other convenient tweaks such as displaying 100.00 instead of 100 . As always make sure to read the documentation.

The other advantage of using the Intl.NumberFormat API is that it future proofs the code. Since it is a native API, it will evolve and adapt as browsers get updated, and so will your code. This is one of the many reasons when given a choice, always use a native implementation over an external library or a polyfill.

If you have any questions or comments about currencies in JS, or if you have other tips, please leave a comment, thanks!

--

--

Arnaud Dostes

Previously Paris and Geneva, currently New York. Can also be found at https://dev.to/arnaud