Floating-point errors occur because many decimal numbers cannot be represented exactly in binary format. As a result, calculations involving floating-point values may produce small precision differences, unexpected comparison results or accumulated rounding errors.
a = 0.1 + 0.2
print(a)
Output
0.30000000000000004
Explanation: 0.1 and 0.2 are stored as approximate binary values. When added together, the result becomes 0.30000000000000004 instead of exactly 0.3.
Common Floating Point Errors
The following examples demonstrate some common floating-point precision issues in Python.
1. Decimal Representation Errors: Some decimal values cannot be represented exactly in binary form, leading to small precision differences.
n = 0.1
print(format(n, ".30f"))
Output
0.100000000000000005551115123126
Explanation: Although 0.1 appears simple, its binary representation is only an approximation, which becomes visible when displayed with high precision.
2. Accumulated Precision Errors: Repeated floating-point operations can accumulate tiny rounding errors over time.
total = 0.0
for _ in range(10):
total += 0.1
print(total)
Output
0.9999999999999999
Explanation: Adding 0.1 ten times does not produce exactly 1.0 because each addition introduces a small approximation error.
3. Floating Point Comparison Issues: Directly comparing floating-point values can produce unexpected results.
a = 0.1 + 0.2
b = 0.3
print(a == b)
Output
False
Explanation: Although both values appear equal, a is actually stored as 0.30000000000000004, causing the comparison to fail.
4. Loss of Precision in Calculations: Very large and very small values used together can cause precision loss.
a = 1e16 + 1
b = a - 1e16
print(b)
Output
0.0
Explanation: value 1 is lost during floating-point representation because it is too small compared to 1e16.
Managing Floating Point Errors
The following techniques can help reduce floating-point precision issues in Python.
1. Rounding Values: Rounding can remove small precision differences when displaying results.
res = 1.2 - 1.0
print(round(res, 2))
Output
0.2
Explanation: round(res, 2) limits the result to two decimal places, removing the unwanted precision digits.
2. Using the decimal Module: The decimal module provides higher precision arithmetic for calculations requiring accurate decimal values.
from decimal import Decimal
res = Decimal("1.2") - Decimal("1.0")
print(res)
Output
0.2
Explanation: Decimal() stores values as exact decimal numbers instead of binary floating-point approximations.
3. Using the fractions Module: Fractions can represent numbers exactly as rational values.
from fractions import Fraction
res = Fraction("1.2") - Fraction("1.0")
print(res)
Output
1/5
Explanation: Fraction() stores values as exact fractions, completely avoiding floating-point precision issues.
4. Comparing Floats with math.isclose(): Instead of using ==, use math.isclose() when comparing floating-point numbers.
import math
a = 0.1 + 0.2
b = 0.3
print(math.isclose(a, b))
Output
True
Explanation: math.isclose() checks whether two values are approximately equal within a small tolerance, making it suitable for floating-point comparisons.
