Home Web Front-end JS Tutorial Financial Precision in JavaScript: Handle Money Without Losing a Cent

Financial Precision in JavaScript: Handle Money Without Losing a Cent

Aug 10, 2024 am 06:45 AM

Financial Precision in JavaScript: Handle Money Without Losing a Cent

In the fast-paced world of finance, precision is everything. It's always better to avoid a million$ loss because of a rounding / precision error.

When it Comes to Money, Think About Datatype

The starting point of this article is the realization that money is not your average basic number that you can use to count the apples in your basket. What do you get when you try to multiply 10€ with 10$? Tough huh… Have you ever found a miraculous $1.546 in the pocket of an old jacket? Yeah I know, this is not really possible either. These silly examples are here to illustrate the fact that money has its own particular rules and can't only be modeled by a simple number. I reassure you, I am not the first one who realized that (and maybe you did realize it way before me). In 2002, the programmer Martin Fowler proposed in the Patterns of Enterprise Application Architecture a way to represent money, with specific attributes and operand rules. For him, the two minimal viable attributes needed for a money datatype were:

amount
currency
Copy after login

This really basic representation will be our starting point to construct a simple but robust monetary model.

Money Amounts, How to Represent Them

A money amount is definitely a particular number: it has a fixed precision (again, you can't have 4.376$ in your pocket). You need to choose a way to represent it that helps you to respect this constraint.

A Naïve Approach, the Native number JavaScript Datatype

Spoiler alert, this is definitely not a good idea if you don't want to see a few cents (if it's not dollars) disappear in the dark world of floating-points number representation.

The Costly Precision Error

If you have some experience with coding in JavaScript, you know that even the most simple calculation can result in a precision error that you would not expect at first. The most obvious and well-known example to highlight this phenomenon is:

0.1 + 0.2 !== 0.3 // true
0.1 + 0.2 // 0.30000000000000004
Copy after login

If this example doesn't fully convince you, I advice you to have a look at this article which deeps dive a bit further into all the problematic calculation results that you can encounter working with JavaScript native number type…

This slight delta in the results may appear harmless to you (with a magnitude of about ~ 10^-16), however in a critical financial application, such error can cascade quickly. Consider transferring funds between thousands of accounts, where each transaction involves similar calculations. The slight inaccuracies add up, and before you know it, your financial statements are off by thousands of dollars. And honestly, we can all agree that when it comes to money, error is not allowed: both legally and to build a trusting relationship with your customers.

Why Such an Error?

The first question I asked myself when encountering the issue in one of my projects is why ? I discovered that the source of the problem is not JavaScript and these imprecisions also affect other modern programming languages (Java, C, Python, …).

// In C
#include <stdio.h>

int main() {
    double a = 0.1;
    double b = 0.2;
    double sum = a + b;
    if (sum == 0.3) {
        printf("Equal\n");
    } else {
        printf("Not Equal\n"); // This block is executed
    }
    return 0;
}

// > Not equal
Copy after login
// In Java
public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total += 5.6;
        total += 5.8;
        System.out.println(total);
    }
}

// > 11.399999999999
Copy after login

In fact, the root cause lies in the standard used by these languages to represent floating-point numbers : the double(or single)-precision floating-point format, specified by the IEEE 754 standard.

IEEE 754 Standard: a Story of Bit Representation

In Javascript, the native type number corresponds to double-precision floating-point numbers, which means that a number is encoded with 64 bits and divided into three parts:

  • 1 bit for the sign
  • 11 bits for the exponent
  • 52 bits for the mantissa (or fraction) which ranges from 0 to 1

Financial Precision in JavaScript: Handle Money Without Losing a Cent

Financial Precision in JavaScript: Handle Money Without Losing a Cent

Then, you need to use the following formula to convert your bit representation into a decimal value:

Financial Precision in JavaScript: Handle Money Without Losing a Cent

An example of double-precision floating-point number representation, an approximation of 1/3 :

0 01111111101 0101010101010101010101010101010101010101010101010101

= (-1)^0 x (1 + 2^-2 + 2^-4 + 2^-6 + ... + 2^-50 + 2^-52) x 2^(1021-1023)
= 0.333333333333333314829616256247390992939472198486328125
~ 1/3
Copy after login

This format allows us to represent a vast range of values, but it can't represent every possible number with absolute precision (just between 0 and 1 you can find an infinity of numbers…). Many numbers cannot be represented exactly in binary form. To loop on the first example, that's the issue with 0.1 and 0.2. Double-point floating representation gives us an approximation of these value, so when you add these two imprecise representations, the result is also not exact.

A possible solution: Arbitrary Decimal Arithmetic

Now that you are fully convinced that handling money amounts with native JavaScript number type is a bad idea (at least I hope you begin to have doubts about it), the 1Billion$ question is how should you proceed ? A solution could be to make use of some of the powerful fixed-precision arithmetic packages available in JavaScript. For example Decimal.js (which is used by the popular ORM Prisma to represent its Decimal datatype) or Big.js.

These packages provide you with special datatypes that allow you to perform calculations with getting rid of precision errors we explained above.

// Example using Decimal.js
const Decimal = require('decimal.js');
const a = new Decimal('0.1');
const b = new Decimal('0.2');
const result = a.plus(b);

console.log(result.toString()); // Output: '0.3'
Copy after login

This approach provides you with another advantage, it drastically extends the maximum value that can be represented, which can become pretty handy when you are dealing with cryptocurrencies for example.
Even if it is really robust, that it not the one I prefer to choose to implement in my web applications. I find it easier and clearer to apply Stripe strategy to only deal with integer values.

Learn from Masters : Stripe, a No-Floating Points Strategy

We, at Theodo Fintech, value pragmatism! We love to take inspiration from the most succeeding companies in the industry. Stripe, the well-known billions$ company specialized in payment services, made the choice to handle money amounts without floating numbers but with integers. To do that, they use the smallest unit of the currency to represent a monetary amount.

// 10 USD are represented by
{
 "amount": 1000,
 "currency": "USD"
}
Copy after login

Currency Minimal Units… Are Not Consistent!

I guess that many of you already know this: all currencies don't have the smallest unit of the same magnitude. Most of them are "two-decimal" currencies (EUR, USD, GBP) which means that their smallest unit is 1/100th of the currency. However, some are "three-decimal" currencies (KWD) or even "zero-decimal" currencies (JPY). (You can find more information about it by following the ISO4217 standard). To handle these disparities, you should integrate to your money data representation the multiplicative factor to convert an amount represented in the smallest unit into the corresponding currency.

Financial Precision in JavaScript: Handle Money Without Losing a Cent

I Chose a Way to Represent Money Amount… OK, But Now, How Do I Round Them?

I guess you already figured it out, you can either work with native number , third party arbitrary-precision packages or integers, calculations can (and will) lead you to floating-point results that you will need to round to your monetary finite precision. As a quick example is never to much, let's say that you handle integer values and contracted a loan of 16k$ with a really precise interest rate of 8.5413% (ouch…). You then need to refund 16k$ plus an additional amount of

1600000 * 0.085413 // amount in cents
//Output in cents: 136660.8
Copy after login

The crux is to properly handle the rounding process of money amounts after calculations. Most of the time, you end up having to choose between three different kinds of rounding:

  • Classic rounding: Round to the closest value and if halfway between two values, round up
  • Banker rounding: Round to the closest value and if halfway between two values, round down if the number is even, and round up if the number is odd (this gives you numerical stability when you have to perform lots of rounding)
  • Custom rounding: based on particular legislation for the currency you use and the use case you are handling

When it comes to roundings, there is not really any "magic sauce": you need to arbitrate depending on your situation. I recommend you always check legislation when you deal with a new currency and a new rounding use case (conversion, money split, interest rates for credits, …). You better follow regulations right away to avoid further troubles. For example, when it comes to conversion rates, most currencies have determined rules about needed precision and rounding rules (you can have a look at the EUR conversion rate rules here).

Conclusion

This article is not exhaustive about all the existing possibilities to handle money amounts in JavaScript and is also not intended to give you a complete/perfect money data model. I tried to give you enough hints and guidelines to implement a representation that proved to be consistent, resilient and which was chosen by big actors of the fintech industry. I hope that you will be able to perform money amount calculations in your future projects without forgetting any cents in your pocket (otherwise don't forget to have a look in your old jacket)!

The above is the detailed content of Financial Precision in JavaScript: Handle Money Without Losing a Cent. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How do I create and publish my own JavaScript libraries? How do I create and publish my own JavaScript libraries? Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser? How do I optimize JavaScript code for performance in the browser? Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

How do I debug JavaScript code effectively using browser developer tools? How do I debug JavaScript code effectively using browser developer tools? Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How do I use source maps to debug minified JavaScript code? How do I use source maps to debug minified JavaScript code? Mar 18, 2025 pm 03:17 PM

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

See all articles