Never Store Money as a Float: Representing Currency in Code
Floating-point math quietly corrupts money. Here is how to store, calculate, and round currency correctly using integer minor units.
Open a console in almost any language and type 0.1 + 0.2. You will not get 0.3. You will get 0.30000000000000004. That tiny tail of digits is harmless when you are plotting a graph. It is a disaster when you are adding up someone's invoice.
If your system touches money — orders, payouts, refunds, wallet balances — the single most important data-modeling decision you will make is how you represent it. Get this wrong and the bugs are subtle, intermittent, and embarrassing.
Why Floats Betray You
Floating-point numbers store values in binary, and most decimal fractions simply have no exact binary representation. One-tenth is a repeating fraction in base 2, the same way one-third is endless in base 10. The computer rounds it to the nearest value it can hold, and that rounding error compounds every time you add, multiply, or accumulate.
For a single transaction the drift is invisible. But financial systems sum thousands of rows, apply percentages for tax and discounts, and reconcile totals against a bank statement that expects an exact match. A few stray fractions of a cent, multiplied across a day of orders, is exactly how your ledger ends up off by a rupiah or two with no explanation.
The rule is simple: never let a value that represents money live in a
floatordouble, not even for a moment.
Store Money as Integer Minor Units
The fix that has quietly powered payment systems for decades is to stop storing money as a fractional amount at all. Instead, store the number of minor units — the smallest indivisible piece of the currency — as a plain integer.
$19.99becomes1999centsRp150.000becomes150000rupiah- A
€5.00refund becomes500cents
Integers are exact. 1999 + 250 is always 2249, forever, on every platform. You only convert back to a human-friendly decimal at the very edge of your system — when you render a receipt or a screen. Internally, everything stays whole.
Most currencies use two decimal places, but not all. The Japanese yen has zero — one yen is already the smallest unit — while the Kuwaiti dinar has three. In everyday Indonesian commerce the rupiah is priced in whole units, so you rarely deal with fractions at all. This is why you should always pair an amount with its currency code and let the currency dictate how many minor units it has.
Rounding Is a Business Decision, Not an Accident
The moment you split a bill, apply an 11% tax, or divide a payout among three sellers, you produce fractions of a minor unit that must go somewhere. Do not let the language's default behavior decide silently.
- Pick a rounding rule on purpose — round half up, round half to even (banker's rounding), or truncate — and apply it consistently.
- When you divide an amount into parts, allocate the leftover unit deliberately so the parts always sum back to the original. Losing or inventing a single cent breaks reconciliation.
- If your language offers a dedicated decimal type — Python's
Decimal, aBigDecimal, a money library — use it for the intermediate math, then land back on integers.
The Takeaway
Money is not a number you eyeball; it is a value that must be provably exact. Store it as integer minor units, always carry the currency alongside it, and make rounding an explicit, tested decision rather than a side effect. Do that from day one and an entire category of "off by a few cents" bugs — the kind that erode trust and swallow afternoons of debugging — never gets the chance to appear.
Build with Abati Technology
We build software that ships — WhatsApp API, developer tools, POS, and mobile apps. Let's talk about your project.
Get in Touch →