Sentry Logo Debug Microservices & Distributed Systems

Trevor I. Lasn

Staff Software Engineer & Engineering Manager

4 min read

Precise Decimal Math in JavaScript with Fraction.js

How to handle exact decimal calculations in JavaScript when floating-point precision isn't good enough

Ever tried to do precise calculations in JavaScript? These issues can cause serious problems, especially when dealing with money, percentages, or any calculations that need to be exact.

This isn’t a JavaScript bug. It’s a fundamental limitation of how computers store decimal numbers, and it affects nearly every programming language. To understand why we need Fraction.js, we first need to understand what’s really happening under the hood.

Computers store numbers in binary (base-2). While this works perfectly for whole numbers, it creates problems with decimals.

In base-10 (our decimal system), we can represent 1/10 simply as 0.1. But in binary, 0.1 is a repeating fraction - like trying to represent 1/3 in decimal (0.333333…). When this gets stored in JavaScript’s 64-bit floating-point format (IEEE 754), it has to be truncated, leading to tiny rounding errors.

You might think BigInt could solve this problem, but it has its own limitations:

BigInt solves precision for whole numbers but can’t handle decimals at all. It’s designed for different use cases like cryptography or very large integer calculations.

A common workaround is to multiply everything by 100 to avoid decimals entirely:

This approach looks simple but falls apart with complex calculations or multiple operations.

Working with Fractions Instead of Decimals

Let’s solve these precision problems using Fraction.js:, a library that handles numbers as fractions instead of floating-point decimals. Just like we learned math in school: 1/3 is more precise than 0.333333.

Fraction.js uses a BigInt representation for both the numerator and denominator, ensuring minimal performance overhead while maximizing accuracy. Its design is optimized for precision, making it an ideal choice as a foundational library for other math tools, such as Polynomial.js and Math.js

Instead of trying to represent decimals in binary, which causes those rounding errors we saw earlier, Fraction.js stores each number as a ratio of whole numbers. For example, 0.1 becomes 1/10 internally. This means our calculations stay exact, just like they would on paper.

Understanding the Limitations

Fraction.js is powerful, but it’s not magic. It works with rational numbers - numbers that can be expressed as a ratio of integers (like 3/4 or 22/7). This makes it perfect for money calculations or simple fractions, but not so great for irrational numbers like π or √2.

While it uses BigInt internally, you’re still working with JavaScript’s number system at the edges.

This means you get more precision than regular decimals, but not infinite precision. Some operations have limitations too. Square roots give approximations rather than exact values, and transcendental functions like sin or cos aren’t supported. Complex numbers are also off the table.

Even with these limitations, Fraction.js is incredibly useful. You can use it to calculate exact values ahead of time, handle money calculations without rounding errors, build educational software that works with fractions, or solve any problem where decimal precision really matters. The key is knowing when to use it and when something else might be more appropriate.


Recommended Engineering Resources

Here are engineering resources I've personally vetted and use. They focus on skills you'll actually need to build and scale real projects - the kind of experience that gets you hired or promoted.


This article was originally published on https://www.trevorlasn.com/blog/fraction-numbers-in-javascript. It was written by a human and polished using grammar tools for clarity.

Interested in a partnership? Shoot me an email at hi [at] trevorlasn.com with all relevant information.