Understanding Floating Point Arithmetic Pitfalls in Python
Table of Contents
If you’ve been using Python for data analysis, you might have encountered a result that seems to defy basic math. Try running this in your console:
>>> 0.1 + 0.2 == 0.3
False
It’s a classic “gotcha” for self-taught programmers. But why is it False? If you run the same comparison with integers, it works exactly as expected:
>>> 1 + 2 == 3
True
The reason lies in how computers handle numbers under the hood: Floating Point Arithmetic.
The Binary Fraction Problem #
Computers represent numbers using binary (base 2). While integers are easy to convert to binary, fractions are much trickier.
A number like 0.1 is a simple decimal fraction, but in binary, it becomes an infinitely repeating fraction: 0.000110011001100110011...
Because computers have finite memory and precision, they must eventually “cut off” this sequence. This results in a tiny approximation error. When you add 0.1 and 0.2, those tiny errors accumulate, meaning the result is almost 0.3, but not exactly.
This isn’t a Python bug—it’s a fundamental property of how double-precision floating-point numbers work in almost every programming language (following the IEEE 754 standard).
A Real-World Engineering Example #
I first encountered this behavior years ago while building relative permeability tables for reservoir simulation. I was using a script to populate values between a starting water saturation \(S_{wirr}\) and a residual oil saturation \(1 - S_{or}\).
In the O&G industry, values like 0.1, 0.2, and 0.3 are common for these parameters. My script was failing to generate values in the correct places because I was performing direct comparisons like if saturation == 0.1:. Because of floating-point inaccuracies, the comparison would occasionally fail even when the math “should” have been correct.
How to Handle Precision #
If you are performing critical engineering calculations or financial transactions where every decimal place counts, you shouldn’t rely on standard floats. Instead, look into Python’s built-in modules designed for precision:
-
Decimal Module: Provides support for fast correctly rounded decimal floating point arithmetic. Official Documentation
-
Fractions Module: Allows you to perform arithmetic using rational numbers (fractions) to maintain absolute precision. Official Documentation
For more details on why this happens, I highly recommend reading the official Python tutorial on Floating Point Arithmetic: Issues and Limitations.
Have you run into these “phantom” errors in your own scripts? How did you solve them?