Python beginners often run into confusion when a calculation like 0.1 + 0.2 fails to return exactly 0.3. Instead, Python gives 0.30000000000000004. This result comes from how computers handle decimal numbers with binary floating point arithmetic. The official Python documentation explains that decimal fractions such as 0.1 usually cannot be represented exactly in binary floating-point notation because their binary expansions repeat without end. Python's float type keeps the closest binary approximation, not the precise decimal value typed by the programmer. This is a result of finite-precision binary representation and appears in many programming languages and systems that use the IEEE 754 floating-point standard.
How Computers Store Decimal Numbers
Computers rely on binary (base 2) to store numbers, so every value is a combination of powers of two. Fractions like 0.5 or 0.25 fit exactly in binary, but 0.1 does not. In binary, 0.1 becomes an endlessly repeating fraction, so Python saves the closest value it can within floating point precision limits. The IEEE 754 double-precision format, used by Python's float type on nearly all platforms, assigns 64 bits per value: 1 sign bit, 11 exponent bits, and 52 fraction bits, with an implicit leading bit for normalized numbers. This setup gives 53 bits of binary significand precision, which is about 15–17 significant decimal digits.
This limitation is similar to writing 1/3 as a decimal: 0.333333... repeats forever, and storing it in a finite space introduces a rounding error. For 0.1, Python actually stores a value just above 0.1, and the same goes for 0.2. Adding these two approximations results in a sum just above 0.3, so Python outputs 0.30000000000000004. The Python documentation states, "The usual representation of a floating-point number is a binary fraction."
To check the exact value Python stores for 0.1, use the as_integer_ratio() method:
print(0.1.as_integer_ratio())
This prints (3602879701896397, 36028797018963968), showing that the stored value is 3602879701896397/36028797018963968, not exactly 1/10. The denominators are powers of two, which reflects the binary storage method.
Demonstrating the Issue in Python
Try this in a Python interpreter:
print(0.1 + 0.2)
The output is:
0.30000000000000004
Checking equality with 0.3 does not work as expected:
print(0.1 + 0.2 == 0.3)False
This behavior appears in other languages like JavaScript, Java, and C# because they also use the IEEE 754 floating point standard. The IEEE 754 standard defines floating-point formats and operations, including finite representations, rounding, signed zero, infinities, and NaN values. Its goal is to provide predictable behavior for real-number calculations across hardware and software, not to make every real number exactly representable.
Why Does print(0.1) Show 0.1?
Even though 0.1 is stored as a slightly different value, Python prints 0.1 because it displays the shortest decimal representation that maps back to the stored binary value. Older Python versions showed more digits of the stored approximation, but modern Python usually picks the shortest decimal that reproduces the same value when read back. The Python documentation notes, "The illusion is one of the most important aspects of floating-point arithmetic." After calculations, the result may not have a simple decimal representation, so Python prints the full precision.
Practical Solutions for Accurate Decimal Calculations
1. Rounding for Display
If you only need to show a result to users, round the value to the number of decimal places you want:
total = 0.1 + 0.2
print(round(total, 2))
print(f"{total:.2f}")Both methods will print 0.3 or 0.30 as needed.
2. Comparing Floats Safely
Comparing floating point numbers with == is unreliable because of these small errors. Use math.isclose() to check if two numbers are close enough within a small tolerance:
import math print(math.isclose(0.1 + 0.2, 0.3))
This returns True, which is usually what you want when working with decimals. The math.isclose() function compares two values using relative and absolute tolerances, letting you set what difference is acceptable for your use case. The Python documentation describes it as a way to "determine whether two values are close in value." Picking the right tolerance matters, since a value that works for scientific measurement may not fit financial or safety-critical needs.
3. Using the decimal Module for Exact Decimal Math
For financial calculations where exact decimal representation is required, use Python's decimal module. The decimal module supports fast, correctly-rounded decimal floating-point arithmetic and lets you set precision and rounding modes. Always create Decimal objects from strings to avoid floating point errors:
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))This prints 0.3 exactly. Passing a float to Decimal() would bring in the float's existing approximation, so the inaccuracy remains. This difference is especially important in financial, accounting, and tax work where decimal representation and specific rounding rules are required.
4. Using the fractions Module for Exact Rational Arithmetic
Python's fractions module gives exact rational arithmetic for values that can be written as ratios of integers. For example, Fraction(1, 10) + Fraction(2, 10) gives exactly 3/10, avoiding the approximation from binary floats. This method is useful for symbolic calculations, ratios, rational measurements, and teaching. The choice between float, Decimal, and Fraction depends on the needed representation, rounding, and performance.
Unexpected Rounding Results
Even the round() function can give surprising results because of floating point storage. For example:
print(round(2.675, 2))
This prints 2.67 instead of 2.68 because 2.675 is stored as a value just below the halfway mark, so it rounds down. This is another effect of binary approximation.
Summary Table: Handling Decimal Arithmetic in Python
SituationRecommended ApproachDisplay a decimal to users | round(x, 2) or f"{x:.2f}"
Check if two decimals are equal | math.isclose(a, b)
Perform exact decimal math | Decimal("0.1") with strings
Practice: Try It Yourself
- Test print(0.1 + 0.2 == 0.3) and predict the result.
- Find another pair of decimals that do not sum to an exact decimal, such as 0.1 + 0.7.
- Use math.isclose() to compare the result safely.
For more on understanding Python errors, see the article How to Read an Error Message: A 3-Step Method for Python, Java, JavaScript and SQL. The technical explanation in this article is based on material originally published by Craftstack Academy and on the official Python documentation on floating-point arithmetic.
