Stop storing money in floating point.
Yes, the screen says 0.30. The screen is being polite.
Binary floating point can’t represent 0.1 or 0.2 exactly. Add them in typical binary64 and you get a value that prints as 0.30000000000000004 if you look hard enough. The display rounds it for you. The reconciliation team does not.
That tiny difference becomes a missing cent when it shows up in a posted amount. Or a whole dollar when it compounds across millions of transactions. The computer did exactly what you told it. That’s the irritating part.
And no, rounding “at the end” doesn’t solve it. Which end? After each operation? At the final total? Before or after aggregation? Rounding is a design decision, not a runtime surprise.
Here’s what actually works:
- Pick a representation that matches the required precision: decimal types, integer minor units, or a proper money type with currency attached.
- Specify the rounding mode and the exact step where it applies.
- Decide whether to round each line item or the aggregate; they can produce different totals.
- Keep currency and scale explicit across every calculation and interface.
Floating point is great for physics simulations. Money is not physics. It’s accounting, and accounting demands exactness, not approximations.
“The difference is too small to matter.” Tell that to the team explaining a one-cent variance to the auditors at month-end close.
The machine did exactly what you told it. The problem is what you told it.
Your reconciliation team has enough hobbies.
