Why You Shouldn't Use Floating Point Math for Money in JavaScript
Published
4 July 2026
Type 0.1 + 0.2 in JavaScript and you probably expect 0.3. Press Run on the examples below to see what you actually get.
console.log(0.1 + 0.2);That result is not a bug in your bundler, your framework, or your laptop. It is how JavaScript stores numbers. And if you are adding prices, tax, discounts, or ledger entries with plain number values, this behaviour can turn a simple checkout into a reconciliation headache.
The problem in one line
JavaScript has a single number type: IEEE 754 double-precision floating point. It is fast, it is everywhere, and it is excellent for science, graphics, and most everyday arithmetic. It is a poor default for money.
console.log(0.1 + 0.2 === 0.3);The language is doing exactly what the spec says. The surprise is ours, because decimal notation hides what the machine is actually storing.
What causes it
Computers store numbers in binary. Many decimal fractions, including 0.1 and 0.2, cannot be represented exactly in a finite number of binary digits, the same way 1/3 cannot be written exactly in decimal.
So JavaScript stores the closest representable value instead. When you add those approximations together, the tiny errors can show up at the least significant digit. With 0.1 + 0.2, that drift surfaces as 0.30000000000000004.
This is not unique to JavaScript. Python, Java, C#, Ruby, and most languages that use standard floating point behave the same way. The difference is that JavaScript gives you only this number type for everyday maths, so you feel the issue sooner.
Where it hurts in real code
The classic REPL example looks harmless. In production, the same mechanism causes problems that are harder to spot.
Totals that look wrong
Sum a few line items and compare the result to a clean decimal:
const items = [0.1, 0.2];const total = items.reduce((a, b) => a + b, 0);
console.log(total);console.log(total === 0.3);Your UI might show $0.30 because formatting rounds for display, while the underlying value is still 0.30000000000000004. Any === check, threshold rule, or "is this cart fully paid?" guard can fail even when the customer sees the right price.
Tax, discounts, and reconciliation
Money rarely stops at addition. Tax rates, percentage discounts, and split payments multiply the chances of drift:
const price = 19.99;const tax = price * 0.075;
console.log(tax);console.log(price + tax);console.log((price + tax).toFixed(2));Finance teams expect totals that tie out to the cent. Floating point totals often tie out to "close enough" until someone exports to CSV, compares against a payment provider, or runs an audit. That is when $21.48925 versus $21.49 becomes a support ticket.
Accumulated error over many operations
One bad addition is easy to dismiss. Hundreds of them in a ledger, payroll run, or trading simulation are not. Each operation keeps the representation error and can compound. You might never see 0.30000000000000004 in the UI, but you can still store values that are a fraction of a cent off, which matters when balances must match exactly.
False confidence from toFixed
Calling toFixed(2) does not fix the underlying number. It returns a string for display. If you convert that string back to a number, or keep doing maths on the original float, the drift is still there. Display rounding and accounting correctness are different jobs.
What to do instead
You do not need to abandon JavaScript numbers entirely. You need to stop treating them as exact decimals.
Round at the money boundary
If you must stay with floats for small apps or quick scripts, round at the precision you actually care about, usually cents:
const toCents = (value) => Math.round(value * 100) / 100;
console.log(toCents(0.1 + 0.2));console.log(toCents(0.1 + 0.2) === 0.3);That pattern is fine for simple cases. Be consistent about when you round: after each line item, or only on the final total? Tax law and your finance team may care. Document the rule and apply it everywhere.
Store integer cents
The approach I reach for in anything handling real money is to store amounts as integers in the smallest currency unit:
const items = [10, 20]; // centsconst total = items.reduce((sum, amount) => sum + amount, 0);
console.log(total);console.log(`$${(total / 100).toFixed(2)}`);console.log(total === 30);Add cents with integer addition. Multiply with care when percentages are involved, often by doing the percentage maths in integers too, or by using a dedicated decimal library for those steps. Format to dollars only when rendering.
Reach for a decimal library when the domain demands it
For multi-currency ledgers, tax engines, or billing systems with complex rounding rules, libraries such as decimal.js or big.js model decimal arithmetic explicitly. They trade a little performance for predictable results. Many databases also expose decimal/numeric types; keep money in those columns, not float columns.
A practical rule of thumb
Use JavaScript floats for counts, ratios, graphics, and analytics where tiny error is acceptable. Do not use them as the source of truth for money.
If you remember one thing from the 0.1 + 0.2 meme, make it this: the number looks decimal, but the maths is binary. Plan for that at the boundary where money enters or leaves your system, and you will avoid an entire class of bugs that only show up after launch, often first seen in a finance Slack channel on a Friday afternoon.
Similar articles

RFC 10008: HTTP Finally Gets a Query Method
For thirty years, complex searches have been squeezed into GET query strings or smuggled through POST. RFC 10008 standardises QUERY: a safe, idempotent HTTP method with a request body. Here is why that matters and when you can actually use it.
3 July 2026

If You're Selling AI as a Cost Cutter, You're Selling It Wrong
Most AI leaders pitch AI on headcount reduction and cost savings. The data says that's the losing strategy, the companies actually winning with AI are the ones selling it as value creation.
2 July 2026

Why Are You Paying So Much for AI Coding Tools?
I switched to DeepSeek and now run massive builds for a few dollars instead of hundreds or thousands. The alternatives are 85-95% cheaper with near-identical performance. So why are you still paying premium prices for AI coding tools?
30 June 2026

A Development Harness for Building Software with AI Agents
Raw models are not agents. Skills chained into a spec-driven pipeline turn an AI coding assistant into something you can actually ship with and keep shipping as requirements change.
29 June 2026
