Python

Python Floating Point Math: What 0.1 + 0.2 Really Means

Explains why Python's floating-point math produces results like 0.30000000000000004, covers IEEE 754 representation, practical workarounds using math.isclose and Decimal, and when precision matters most for developers.

August 2026 8 min read 13 views 0 hearts

The Surprising Truth About Python's Floating Point Math

When a new developer at PythonSkillset first runs 0.1 + 0.2 and gets 0.30000000000000004, they often think their computer is broken. But it's not broken - it's actually working exactly as designed. This isn't a Python quirk either. It's a fundamental property of how computers handle decimal numbers.

Why Computers Can't Count Perfectly

Here's the thing: computers work in binary (base-2), but humans count in decimal (base-10). Most decimal fractions can't be represented exactly in binary, just like how 1/3 can't be written as a clean decimal (it's 0.33333...).

Think about it this way: In decimal, we can write 1/10 as 0.1 - clean and simple. But in binary, 1/10 becomes an infinitely repeating number: 0.0001100110011... The computer has to cut this off somewhere, which introduces tiny errors.

Python's Approach: Float Is Just a Name

In Python, floating-point numbers are implemented using the double-precision IEEE 754 standard. This gives you about 15-17 decimal digits of precision. The keyword float in Python maps directly to the C double type - it's not really a "float" at all by traditional C definitions.

Here's a practical example from PythonSkillset's teaching code:

# You might expect this to be True
print(0.1 + 0.2 == 0.3)  # False!

# Here's what's actually happening
print(0.1 + 0.2)  # 0.30000000000000004

When Precision Matters Most

Financial calculations are the classic example where this bites people. If you're working on a banking app at PythonSkillset, never store currency in floats. One day, your app will show someone owing $0.30000000000000004 in interest.

Instead, use Python's decimal module for money:

from decimal import Decimal

price = Decimal('19.99')
tax = Decimal('1.60')
total = price + tax
print(total)  # 21.39, exactly what you expect

Notice we used strings in the Decimal constructor - that's important. If you pass Decimal(19.99), you're already passing a float with rounding errors.

Practical Workarounds

For most scientific computing needs, the built-in float is perfectly fine. The errors are tiny - typically less than 1 part in 10^15. But when you need to compare floats, never use ==. Instead, check if they're close enough:

import math

a = 0.1 + 0.2
b = 0.3
print(math.isclose(a, b))  # True

You can also set tolerance levels with math.isclose:

print(math.isclose(a, b, rel_tol=1e-9))  # relative tolerance
print(math.isclose(a, b, abs_tol=1e-12))  # absolute tolerance

What About Very Large or Very Small Numbers?

Python floats can represent numbers from about 10^-308 to 10^308. Outside that range, you get special values: - inf for infinity (overflow) - -inf for negative infinity - nan for "not a number" (when math doesn't make sense)

print(1e308 * 10)  # inf
print(1e-308 / 10)  # 0.0 (underflow)
print(float('nan') + 5)  # nan

The Decimal Module's Hidden Cost

While Decimal solves precision issues, it's about 10-20 times slower than native floats. So for data science or graphics work, stick with floats. For financial calculations or any case where exact decimal representation matters, pay the performance cost and use Decimal.

A Real-World Lesson

At PythonSkillset, we once had a user who couldn't figure out why their physics simulation gave inconsistent results after running for an hour. They were comparing positions with == instead of checking if positions were close enough. Over time, tiny floating-point errors accumulated, and their simulation "broke." The fix was simple - use tolerance-based comparisons.

The Bottom Line

Python's floating-point math isn't buggy - it's doing exactly what the IEEE 754 standard says it should. Understand its limitations, use Decimal when precision is critical, compare with tolerance, and you'll avoid the traps that catch most developers.

That unexpected 0.30000000000000004 isn't a bug. It's a reminder that computers think in binary, but we live in a decimal world.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.