Skip to content

Why Does 64 ** (1/3) Return 3.999999 Instead of 4 in Python?

Problem

When I calculated the cube root of 64 in Python, I got this unexpected result:

>>> 64 ** (1/3)
3.9999999999999996

I expected exactly 4, but Python returned 3.9999999999999996. At first glance, this looked like a bug. Is Python’s math broken?

Environment

  • Python 3.11 (tested on 3.8+ as well)
  • macOS and Linux
  • Default Python REPL

What happened?

I was working on a simple math problem when I tried to calculate the cube root of 64:

cube_root_test.py
# Simple cube root calculation
result = 64 ** (1/3)
print(f"Cube root of 64: {result}")
print(f"Is it equal to 4? {result == 4}")

When I ran this code:

Terminal window
$ python cube_root_test.py
Cube root of 64: 3.9999999999999996
Is it equal to 4? False

I was confused. The math says the cube root of 64 is exactly 4, so why is Python giving me this strange result?

Let me try a few more tests to understand what’s happening:

>>> 1/3
0.3333333333333333
>>> (1/3).hex()
'0x1.5555555555555p-2'
>>> 0.1 + 0.2
0.30000000000000004

I can see the pattern now. The fraction 1/3 is stored as 0.3333333333333333 (truncated), and the hex representation shows repeating 5s in binary. Even simple addition like 0.1 + 0.2 doesn’t give exactly 0.3.

How to solve it?

I tried several approaches to get the expected result.

Solution 1: Round the result

The simplest fix is to round the result to a reasonable number of decimal places:

solution_round.py
result = round(64 ** (1/3), 10)
print(result) # 4.0
# For comparison with 4
print(result == 4) # True

This works for most display purposes and general calculations. The round() function returns 4.0, which compares equal to 4.

Solution 2: Use math.isclose() for comparisons

When comparing floating-point numbers, I should use math.isclose() instead of ==:

solution_isclose.py
import math
result = 64 ** (1/3)
print(math.isclose(result, 4)) # True
print(math.isclose(result, 4, rel_tol=1e-9)) # True with stricter tolerance

This checks if two numbers are close enough within a relative tolerance, which is the proper way to compare floats.

Solution 3: Use Decimal for exact precision

For applications requiring precise decimal arithmetic (like financial calculations), I can use the decimal module:

solution_decimal.py
from decimal import Decimal, getcontext
# Set precision high enough for our calculation
getcontext().prec = 20
result = Decimal(64) ** (Decimal(1) / Decimal(3))
print(result) # 3.9999999999999999999
# Or quantize to specific decimal places
result_quantized = (Decimal(64) ** (Decimal(1) / Decimal(3))).quantize(Decimal('1.00'))
print(result_quantized) # 4.00

The Decimal module performs exact decimal arithmetic instead of binary floating-point, avoiding the 1/3 representation issue.

The reason

The core issue is that Python’s float type uses IEEE 754 double-precision binary floating-point format, which cannot exactly represent the fraction 1/3.

Here’s why:

  1. In binary, 1/3 is a repeating fraction: Just like 1/3 = 0.333… in decimal, in binary it’s 0.0101010101… (repeating forever).

  2. Limited precision: IEEE 754 doubles have 53 bits of precision, so the binary representation must be truncated.

  3. Small errors compound: When I compute 64 ** (1/3), Python uses the truncated value of 1/3 (approximately 0.3333333333333333), not the exact fraction.

  4. The result is actually correct: The value 3.9999999999999996 is the closest IEEE 754 double-precision float to the true mathematical answer.

I can verify this isn’t just a Python problem:

// JavaScript console
Math.pow(64, 1/3) // 3.9999999999999996
// Java
Math.pow(64, 1.0/3) // 3.9999999999999996
// C++
pow(64, 1.0/3) // 3.9999999999999996

All languages using IEEE 754 floating-point have the same behavior. This is a fundamental limitation of binary floating-point representation, not a Python bug.

Summary

In this post, I explained why 64 ** (1/3) returns 3.9999999999999996 instead of exactly 4 in Python. The key point is that floating-point numbers are approximations, not exact values. The fraction 1/3 cannot be represented exactly in binary, so Python uses an approximation that’s very close but not perfect.

For practical work:

  • Use round() for display purposes
  • Use math.isclose() for float comparisons
  • Use Decimal when precision is critical (like financial calculations)

Python is working correctly—the result is the closest possible representation in IEEE 754 floating-point format.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments