Float Data Type in Python

Learn how Python floats work with IEEE 754 double precision, why 0.1 + 0.2 is not exactly 0.3, and how to handle floating-point arithmetic correctly.

5 min read

Python floats are the language's built-in type for numbers with fractional parts, and they are implemented using the IEEE 754 double-precision binary floating-point standard that your computer's processor supports directly in hardware. This means float arithmetic is fast, but it also means that floats inherit a fundamental limitation of binary floating-point representation: many decimal fractions that look simple to a human, like 0.1 or 0.3, cannot be stored exactly in binary, just as 1/3 cannot be written exactly in decimal. Understanding this limitation and how to work with it is essential before you use floats for anything where exact values matter.

If you have read the articles on Python data types and the integer data type, you already know that integers handle whole numbers with unlimited precision. Floats handle the rest of the number line, from tiny scientific quantities to astronomical distances, but they do so with a fixed precision of approximately 15 to 17 significant decimal digits.

Creating floats and the representation surprise

Any number with a decimal point or an exponent is a float in Python. Writing 3.14, -0.001, or 2.0 all produce float objects. You can also use scientific notation with an e or E to indicate powers of ten: 1.5e-3 means 1.5 times 10 to the power of negative 3, which is 0.0015. The float constructor converts other types when the conversion is meaningful. Passing an integer returns the equivalent float, and passing a string parses it into a float value.

The most famous surprise in floating-point arithmetic occurs when you add two seemingly simple decimals:

pythonpython
print(0.1 + 0.2)            # 0.30000000000000004
print(0.1 + 0.2 == 0.3)     # False

The numbers 0.1 and 0.2 cannot be represented exactly in binary, so each is stored as the closest binary approximation. Their sum is also an approximation, and it differs slightly from the binary approximation of 0.3. The difference is about 5.55 times 10 to the power of negative 17, which is invisibly small in most printed output but causes exact equality comparisons to fail. This is not a Python bug; it is a consequence of how all IEEE 754 floating-point hardware works, and every language that uses hardware floats has the same behavior.

Comparing floats safely

Because exact equality comparisons are unreliable with floats, Python's math module provides the isclose function for comparing floats with a tolerance. You specify a relative tolerance, an absolute tolerance, or both, and the function returns True if the values are within that tolerance of each other. The relative tolerance defaults to 1e-9, which is appropriate for most everyday calculations.

For display purposes, f-string formatting is the right tool. Writing f"{value:.2f}" rounds the value to two decimal places for display without changing the underlying float object. This is the correct approach for presenting currency, percentages, or measurements to users. The built-in round function also rounds floats, but it uses banker's rounding where halfway cases round to the nearest even number. This means round(2.5) returns 2 rather than 3, which avoids upward bias when rounding large datasets but surprises beginners who expect standard rounding.

Special float values

IEEE 754 defines several special float values that Python surfaces directly. Positive and negative infinity represent values that exceed the maximum representable float, and they behave as expected in comparisons and arithmetic. Dividing a positive number by zero produces positive infinity. NaN, which stands for Not a Number, represents the result of an undefined operation like zero divided by zero. NaN has the unusual property that it is not equal to itself, so comparing NaN to NaN returns False. To check for NaN, use the math.isnan function rather than an equality comparison:

pythonpython
import math
 
print(float('inf') > 999999)     # True
print(math.isnan(float('nan')))  # True

When to use Decimal instead of float

The decimal module provides a Decimal type that stores numbers in base-10 rather than binary, which means it can represent decimal fractions like 0.1 exactly. Decimal arithmetic is slower than float arithmetic because it is implemented in software rather than hardware, but for financial calculations, invoice totals, or any scenario where 0.1 plus 0.2 must equal exactly 0.3, Decimal is the correct choice.

The rule of thumb is straightforward: use float for scientific measurements, graphics coordinates, statistics, and machine learning where a tiny representation error is acceptable. Use Decimal for money, accounting, and any domain where decimal fractions must add up to exact values. Python gives you both tools and trusts you to choose the right one for the task. The next article on the boolean data type covers a simpler type with only two possible values, but one that is equally fundamental to how Python programs make decisions.

Rune AI

Rune AI

Key Insights

  • Python floats use IEEE 754 double precision (64-bit) with about 15-17 significant digits.
  • Decimal fractions like 0.1 cannot be represented exactly in binary floating-point.
  • Compare floats with math.isclose(), not ==, when tolerance matters.
  • round() uses banker's rounding; format strings like f'{x:.2f}' round for display.
  • Use the Decimal module for exact decimal arithmetic in financial applications.
  • Scientific notation like 1.5e-3 is valid Python syntax for float literals.
RunePowered by Rune AI

Frequently Asked Questions

Why does 0.1 + 0.2 not equal 0.3 in Python?

Python floats use IEEE 754 binary floating-point representation, which cannot represent decimal fractions like 0.1 exactly, just as you cannot represent 1/3 exactly in decimal. The values 0.1 and 0.2 are approximated, and their sum is slightly different from the approximation of 0.3. Use math.isclose() for float comparisons or the Decimal module for exact decimal arithmetic.

How do I round a float to a specific number of decimal places?

Use the built-in round() function: round(3.14159, 2) returns 3.14. Be aware that round() uses banker's rounding (round half to even), so round(2.5) returns 2, not 3. For display purposes, use f-string formatting like f'{value:.2f}' which rounds for presentation without changing the underlying value.

What is the difference between float and Decimal in Python?

float uses hardware-accelerated binary floating-point and is fast but imprecise for decimal fractions. Decimal from the decimal module uses base-10 representation and can represent decimal fractions exactly, making it suitable for financial calculations. Decimal is slower and uses more memory but avoids the representation errors inherent in binary floating-point.

Conclusion

Python floats give you fast, hardware-accelerated arithmetic for real numbers, at the cost of small representation errors for decimal fractions. Understanding where these errors come from and how to work around them with rounding, tolerance comparisons, and the Decimal module separates confident Python programmers from beginners who get surprised by 0.1 + 0.2.