Battling Floating Point Errors in my JS Mortgage Calculator

2026-01-17

Debugging Console

So, I was building this mortgage calculator, right? Simple stuff, I thought. Just some interest formulas, a few inputs, loop through 360 months... easy peasy. I was knocking it out on a Tuesday night, feeling pretty good about myself.

Then I ran the first test case.

You know that feeling when you expect 100 + 200 to be 300, but the computer looks you in the eye and says 300.00000000000004?

Yeah. That.

The "Incident"

I was working on the amortization schedule. The logic is straightforward:

  1. Calculate monthly interest.
  2. Subtract interest from the monthly payment to get principal.
  3. Subtract principal from the balance.

I fired up the app, entered a $500,000 loan, and scrolled to the bottom of the table. Month 360. The balance should be exactly $0.00.

Instead, it was $-0.00000000000213.

"Close enough," you might say. "Who cares?"

Well, I care. And more importantly, any user who sees "$-0.00" on their financial report is going to think my app is broken. In finance, trust is everything. If I can't add numbers correctly, why would you trust me with your lease agreement or tax breakdown?

I opened up the console, thinking maybe I messed up a variable updates. Nope. It was just JavaScript doing JavaScript things.

> 0.1 + 0.2
0.30000000000000004

I stared at the screen. I knew about floating point errors—we all learn about them in CS 101—but seeing it actually break my beautiful UI was a personal attack.

Why does this even happen?

So I grabbed a marker and went to my whiteboard (okay, it was a napkin first, but let's pretend).

Computers don't think in nice, clean base-10 numbers like we do. They think in binary. Some numbers, like 0.5, represent perfectly in binary (0.1). But others, like 0.1, are repeating decimals in binary, kind of like how 1/3 is 0.333333... in base-10.

IEEE 754 Whiteboard Diagram

Because memory is finite, the computer eventually has to cut it off. That "cutting off" is where the tiny error comes from. And when you do that math 360 times in a loop? Those errors compound. My tiny 0.00000000000000004 error grew up to be a visible nuisance.

The Fix: Integers or Libraries?

I had two choices:

  1. Use a Library: decimal.js or big.js. Reliable, but heavy. I didn't want to bloat my bundle size for a simple calculator.
  2. The "Cents" Method: Convert everything to integers.

I went with the Cents Method. Instead of tracking "dollars" ($150.25), I tracked "cents" (15025). Integers are safe in JavaScript up to 9 quadrillion (thanks, MAX_SAFE_INTEGER), so for mortgages, we're good.

Here is what the fix looked like in TypeScript:

// The dangerous way ❌
const interest = balance * (rate / 12);

// The safe way (Integer Math) ✅
const balanceCents = Math.round(balance * 100);
const monthlyRate = rate / 12;
const interestCents = Math.round(balanceCents * monthlyRate);
const interest = interestCents / 100;

It’s a bit more verbose, sure. You have to remember to multiply and divide by 100 constantly. But the peace of mind? Worth it.

The Result

After refactoring the core logic engines to use integer-based math, I re-ran the standard test cases.

Performance Dashboard

More importantly, the calculation speed didn't suffer. In fact, removing some of the toFixed string parsing hackery I had tried earlier actually made it faster.

Closing Thoughts

If you're building anything involving money—even a simple calculator—do not trust floating point math. It will betray you when you least expect it.

It’s tempting to just Math.round(result * 100) / 100 at the very end (the "display layer" fix), but that hides the internal drift. If your amortization schedule adds up to a different number than your total summary, users will notice.

Fix it at the core. Use integers, or use a library if you're dealing with crypto or scientific precision.

Now, if you'll excuse me, I have a Commercial Lease Calculator to finish—and yes, it uses integer math.

ADVERTISEMENT

Fixed Calculator

See the result of my debugging battles.

DISCLAIMER: FOR INFORMATIONAL PURPOSES ONLY

The calculations, information, and tools provided by Web Ocean Finance are for educational and informational purposes only. They do not constitute financial, legal, tax, or professional advice. While we strive for accuracy, laws and regulations vary by jurisdiction and change over time. You should consult with a qualified professional (attorney, CPA, or financial advisor) before making any decisions based on these results. Web Ocean Digital assumes no liability for errors, omissions, or actions taken in reliance on this information.