PythonMastery
reference 3 min read · lesson 55 of 60 in Errors

TypeError: 'float' object cannot be interpreted as an integer

1 · The lesson

read

What this error means

You gave a float — a number like 3.0 or 2.5 — to something that only works with whole numbers, and Python refused to round it for you. range() is the usual culprit, but random.randint(), str.zfill(), list.pop(), chr() and math.factorial() all raise the same error for the same reason.

Python won't convert even 3.0, which looks harmless. The rule is about the type, not the value: a float might be 3.0 today and 2.9999999999999996 after the next calculation, so Python makes you decide how to turn it into an int.

When you see it

python
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    for i in range(half):
             ~~~~~^^^^^^
TypeError: 'float' object cannot be interpreted as an integer

When the float goes into a library function, the last frames are inside the library and the line you need is the one in your file:

python
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    restock = random.randint(1, stock * 0.25)
  File "C:\Users\Ada\AppData\Local\Programs\Python\Python313\Lib\random.py", line 340, in randint
    return self.randrange(a, b+1)
           ~~~~~~~~~~~~~~^^^^^^^^
  File "C:\Users\Ada\AppData\Local\Programs\Python\Python313\Lib\random.py", line 316, in randrange
    istop = _index(stop)
TypeError: 'float' object cannot be interpreted as an integer

Why it happens

Almost always it is the / operator. In Python 3, / always returns a float, even when the division is exact:

python
orders = ["#1001", "#1002", "#1003", "#1004", "#1005", "#1006"]

print(len(orders) / 2)          # 3.0, a float, even though 6 divides evenly
print(type(len(orders) / 2))
print(len(orders) // 2)         # 3, an int

So this innocent-looking loop fails, because half is 3.0:

python
orders = ["#1001", "#1002", "#1003", "#1004", "#1005", "#1006"]
half = len(orders) / 2
for i in range(half):
    print(orders[i])

The other sources of stray floats: multiplying by a percentage (stock * 0.25), anything from math.sqrt() or statistics.mean(), numbers read from JSON or a CSV and converted with float(), and round(x, 0), which — unlike round(x) — gives back a float.

The same mistake, different words

Use a float where Python wants an int in other places and the wording changes, which hides that it is the same bug:

CodeMessage
range(6 / 2)'float' object cannot be interpreted as an integer
"-" * (40 / 2)can't multiply sequence by non-int of type 'float'
[0] * (n / 2)can't multiply sequence by non-int of type 'float'
name[len(name) / 2]string indices must be integers, not 'float'
orders[len(orders) / 2]list indices must be integers or slices, not float

Every row has the same fix.

How to fix it

Use // when you mean "how many whole times". Floor division returns an int when both sides are ints, and it is what you almost always want for halves, pages and batches:

python
orders = ["#1001", "#1002", "#1003", "#1004", "#1005", "#1006", "#1007"]

half = len(orders) // 2
for i in range(half):
    print(orders[i])

name = "Grace"
print("Middle letter:", name[len(name) // 2])
print("-" * (40 // 2))

Use int(), round() or math.ceil() when the float comes from real arithmetic — and choose deliberately, because they disagree:

python
import math

stock = 125
quarter = stock * 0.25            # 31.25

print(int(quarter))               # 31  - drops the fraction (towards zero)
print(round(quarter))             # 31  - nearest whole number
print(math.ceil(quarter))         # 32  - always rounds up
print(round(quarter, 0))          # 31.0 - still a float, still breaks range()
print(int(-7 / 2), -7 // 2)       # -3 -4: int() and // differ for negatives

For "how many pages do 7 invoices need at 3 per page", math.ceil(7 / 3) (or -(-7 // 3)) is right and int(7 / 3) loses the last page. For a random restock amount, round() is fine:

python
import random

random.seed(42)
stock = 120
restock = random.randint(1, round(stock * 0.25))
print(f"Restocking {restock} of {stock}")

Check the value isn't secretly fractional. If int() silently dropping .5 would be a bug, test first: if not total.is_integer(): raise ValueError(...). Better to fail loudly than to process 2 orders out of 2.5.

When you'd actually see this in real code

  • Splitting a dataset into training and test halves with range(len(rows) / 2).
  • Pagination: range(total_items / per_page) for page links.
  • Centring text in a terminal report: " " * ((width - len(title)) / 2).
  • Porting old Python 2 code, where / between two ints did floor division — the same line silently changed meaning in Python 3.
  • A config value like "retries": 3.0 from JSON, passed straight into range().

See Also

Found this useful? Share it with a friend who’s learning Python.