← back

Money is not a float

Why 0.1 + 0.2 never quite equals 0.3, and why that matters a lot when the number is money.

Type this in a JavaScript console: 0.1 + 0.2. You will get 0.30000000000000004. Not 0.3. And for most of my life, that tiny error would have been a rounding footnote. Now it’s a bug I design entire systems around.

Here’s the thing nobody warns you about: floating-point arithmetic is an approximation. Not a broken one: a deliberate one. A float is a binary representation, and most decimal fractions don’t have an exact binary equivalent. You can’t represent 0.1 precisely in base-2 any more than you can represent 1/3 precisely in base-10.

The problem, made concrete

Imagine you’re a warehouse. You sell 0.1 kg of something, a few times. Each tiny sale is a float. After a few transactions, the sum is off by a few billionths. For most data that’s fine. For inventory cost, for COGS that gets posted to a ledger, it’s not fine, because:

  1. The error compounds across thousands of transactions.
  2. It’s not symmetric; it doesn’t cancel out. It drifts in one direction.
  3. Someone has to explain the variance, and “the computer rounded” is not an explanation an auditor accepts.

The fix: integer cents

The rule is older than computers. Never store money as a float; store it as a fixed-point value, i.e. an integer number of the smallest unit (cents, or a chosen fractional unit), and do arithmetic on integers.

// Bad: 0.30000000000000004
const price = 0.1 + 0.2;

// Good: exact, because the smallest unit is an integer
const price_cents = 10 + 20; // 30 cents

Then you divide only when you need to display a currency, and you do that division in a way that’s exact for the decimal you’re showing.

What I actually use

In FIFO Inventory, the math is in decimal.js. It does base-10 arithmetic on a mantissa/exponent that’s exact for decimal fractions. It’s the difference between “trust me, it’s fine” and “this number is correct by construction.”

For an accountant, that’s not a pedantic detail. It’s the entire job. You’re not allowed to be mostly right about money. A system that knowingly introduces a drift and calls it a rounding error is a system that has chosen convenience over correctness, and anyone who’s ever been on the wrong side of that variance knows the cost.

Takeaway

If you build anything that touches money, follow the rule:

  • No floats for money. Ever.
  • Use integer cents (or a fixed-point/decimal type).
  • Aggregations are exact; only display-time conversion is allowed to round.
  • If a number can’t be represented exactly, don’t present it as if it is.

I keep this rule the way other people keep a swear jar. It’s a promise to the person who eventually has to defend the numbers, which in my case is me, at 10pm, with a calculator.