Skip to content
Innovialabs

Why 0.1 + 0.2 ≠ 0.3: Floating Point and Money in Code

Practice4 min

In short

Floats store numbers approximately in binary, so money should be kept as integers in minor units (cents, tiyin) or in decimal types such as Decimal and NUMERIC.

The short answer

Most languages store fractional numbers using the IEEE 754 standard — in binary. In binary, 0.1 is an infinite fraction, just like 1/3 in decimal. The computer cuts it off, so memory holds a value that is very close but not exact.

0.1 + 0.2            // 0.30000000000000004
0.1 + 0.2 === 0.3    // false

For scientific work this error usually does not matter. For money it does: a cent lost in one operation becomes a mismatch in a report, and the amount charged no longer matches the receipt.

Rule: never store or calculate money in float or double.

How a float works

An IEEE 754 number has three parts: a sign, a mantissa (the significant digits) and an exponent (where the point goes). A double gives roughly 15–17 significant decimal digits.

This leads to two kinds of problems:

  • Unrepresentable fractions. 0.1, 0.2 and 0.7 cannot be written exactly in binary.
  • Precision loss on large numbers. When a number is very large, its lower digits simply do not fit in the mantissa.

Errors accumulate: add 0.1 a thousand times and the result is visibly different from 100.

Option 1: integers in minor units

Store the amount as an integer in the smallest unit of the currency: cents for dollars, tiyin for Uzbek so'm.

  • 15,000.50 so'm → 1500050 tiyin
  • $19.99 → 1999 cents

Integers add and subtract exactly. You convert to a human-readable format only when displaying.

price_tiyin = 1_500_050
qty = 3
total_tiyin = price_tiyin * qty          # 4,500,150, exact
print(f"{total_tiyin / 100:,.2f} UZS")   # display only

Keep in mind that currencies differ in the number of decimal places. ISO 4217 gives the Uzbek so'm two, although tiyin are rarely seen in cash circulation. Many systems keep so'm amounts in whole so'm — that is fine as long as it is written down in the requirements.

Option 2: decimal types

Decimal types store numbers in base 10 and calculate without binary errors.

EnvironmentType
Pythondecimal.Decimal
JavaBigDecimal
C#decimal
PostgreSQL, MySQLNUMERIC(p, s) / DECIMAL(p, s)
JavaScriptthird-party decimal arithmetic libraries
from decimal import Decimal, ROUND_HALF_UP

a = Decimal("0.1") + Decimal("0.2")   # Decimal('0.3')
vat = (Decimal("15000.50") * Decimal("0.12")).quantize(
    Decimal("0.01"), rounding=ROUND_HALF_UP
)

Create a Decimal from a string, not from a float: Decimal(0.1) inherits the same error.

Rounding is a business rule

Even with exact types, money has to be rounded: taxes, discounts, exchange rates. Decide upfront:

  • Rounding mode. Half-up as taught at school, or banker's rounding (half to even). Python's built-in round(), for example, uses banker's rounding.
  • When to round. Per receipt line or once on the total — the results can differ.
  • Splitting amounts. 100 does not divide evenly by three: 33.33 + 33.33 + 33.34. The remainder is explicitly assigned to one of the parts.

Project checklist

  1. In the database — NUMERIC or an integer in minor units, never FLOAT or REAL.
  2. In the API — amounts as a string ("15000.50") or an integer in minor units, with a currency code next to them.
  3. The currency is stored with the amount, not assumed.
  4. Rounding rules are written into the requirements and covered by tests.
  5. Exchange rates are stored with enough precision and a date.
  6. The frontend only displays amounts; the server does the final calculation.

Common mistakes

  • Comparing floats with ==.
  • Using parseFloat on amounts from a form and then doing arithmetic.
  • A money type or float in JSON with no agreement on precision.
  • Rounding at every intermediate step without a rule.

FAQ

For display, yes; for calculations, it is risky. Errors build up across a chain of operations, and rounding at the end does not always bring back the correct result.

We can help with this

If you'd rather get the result than figure it all out yourself — this is what we do every day.

Discuss a project

Read next

Have an idea or a task? Tell us about it

We'll reply within one business day and propose a solution. The consultation is free.