principlejavascriptCritical
Store money as integers (cents), never as floats
Viewed 0 times
moneycentsintegerfloating pointcurrencyprecisionrounding errorDinero
Problem
Storing currency amounts as floating-point numbers causes rounding errors that accumulate and produce incorrect totals in financial calculations.
Solution
Always store and compute money as integers in the smallest currency unit:
For complex calculations use a library:
// WRONG — floating point errors
const price = 19.99;
const tax = price * 0.08;
console.log(price + tax); // 21.5892 — not what you want
// CORRECT — integer cents
const priceCents = 1999; // $19.99
const taxCents = Math.round(priceCents * 0.08); // 160 cents = $1.60
const totalCents = priceCents + taxCents; // 2159 cents = $21.59
// Display only
const display = (cents) => `${(cents / 100).toFixed(2)}`;
console.log(display(totalCents)); // '$21.59'
// Database schema
// amount INTEGER NOT NULL -- always in cents
// currency CHAR(3) NOT NULL DEFAULT 'USD'
// Parsing user input
const parseAmount = (str) => Math.round(parseFloat(str) * 100);For complex calculations use a library:
import Dinero from 'dinero.js';
const price = Dinero({ amount: 1999, currency: 'USD' });
const tax = price.multiply(0.08);
console.log(price.add(tax).toFormat('$0.00'));Why
IEEE 754 floating-point cannot represent 0.1 exactly. 0.1 + 0.2 === 0.30000000000000004 in JavaScript. Integer arithmetic is exact.
Gotchas
- Be careful when converting: 19.99 * 100 = 1998.9999999999998 — always use Math.round() when converting float to cents
- Different currencies have different subunits: JPY has no cents, KWD has 3 decimal places
- When dividing (splitting a bill), decide on your rounding strategy and document it
- Stripe, PayPal, and most payment APIs already expect amounts in the smallest currency unit
Revisions (0)
No revisions yet.