Python Numbers: int, float, and complex Explained

Python has three built-in numeric types: int for whole numbers, float for decimal numbers, and complex for numbers with a real and imaginary part. They work together in arithmetic, but they do not behave the same way, so it helps to know when Python keeps exact values and when it switches to approximation. This article explains how each type works, how Python chooses results, and the mistakes beginners make with numeric code.

Difficulty: Beginner

Helpful to know first: basic Python variables, assignment with =, and simple arithmetic operators like + and *.

How Python Stores Whole Numbers, Decimals, and Complex Values

Python chooses a numeric type based on the value you write and the kind of math you need. A whole number such as 42 is an int. A number with a decimal point such as 42.0 is a float. A complex number uses the form a + bj, where a is the real part and b is the imaginary part.

Python keeps int values exact. It stores float values in binary floating-point format, which is fast and useful for most decimal calculations but can create tiny rounding surprises. complex values store two floats: one for the real part and one for the imaginary part.

Python
print(type(7))          # Output: <class 'int'>
print(type(7.0))        # Output: <class 'float'>
print(type(7 + 3j))     # Output: <class 'complex'>

This shows the three numeric types directly. The value you write determines the type, and the type affects later operations.

Using int for Exact Whole-Number Math

int is the type to use when you need exact counting: items in a cart, loop counters, ages, page numbers, or any value that should never contain a fraction. Python integers can grow as large as memory allows, so you do not need to pick a fixed size such as 32-bit or 64-bit for ordinary Python code.

Integer arithmetic stays exact. Division is the main exception: the / operator always returns a float, even when both sides are whole numbers. If you want the quotient without the remainder and still want an integer result, use //.

Python
print(10 + 3)    # Output: 13
print(10 - 3)    # Output: 7
print(10 * 3)    # Output: 30
print(10 / 3)    # Output: 3.3333333333333335
print(10 // 3)   # Output: 3
print(10 % 3)    # Output: 1

These operators are the core of numeric code in Python. The division operators are especially important because they do not all return the same type.

Using float for Decimal Values and Approximate Calculations

float is the type to use for measurements, averages, scientific values, and other numbers that can have fractional parts. It supports arithmetic in the same way int does, but a float is an approximation of a real number, not a perfect decimal representation for every value.

The most important beginner surprise is that some decimal values cannot be represented exactly in binary. That is why simple-looking expressions can produce results with a long tail of digits.

Python
print(0.1 + 0.2)   # Output: 0.30000000000000004
print(round(0.1 + 0.2, 1))  # Output: 0.3

The first line shows the representation issue. The second line shows one common way to present a rounded result, but rounding does not change how the number is stored; it only changes the value you get back from round.

Why float comparisons need care

Because floats can contain tiny representation errors, comparing them with == can fail even when the values look the same on screen. A safer pattern is to compare whether the difference is small enough for your use case.

Python
a = 0.1 + 0.2
b = 0.3

print(a == b)                 # Output: False
print(abs(a - b) < 1e-9)   # Output: True

This difference matters in finance, measurement, and any code that tests exact decimal equality. The closer your work is to real-world quantities, the more likely you are to need a tolerance.

Using complex for Two-Part Numbers

complex numbers are built into Python and are written with the imaginary unit j, not i. Python uses them for math that has a real and imaginary component, such as signal processing, electrical engineering, and some scientific formulas.

You can access the real and imaginary parts with .real and .imag. Like floats, complex numbers are immutable: operations create new values instead of changing the original number.

Python
z = 2 + 3j

print(z)           # Output: (2+3j)
print(z.real)      # Output: 2.0
print(z.imag)      # Output: 3.0
print(z * 2)     # Output: (4+6j)

Notice that the real and imaginary parts are returned as floats. That is normal, even if you start with whole numbers.

How Python Chooses a Result Type in Mixed Math

When you mix numeric types, Python follows promotion rules. The important rule is simple: if one side is a float, the result is usually a float; if one side is complex, the result is complex. Integers are promoted to fit the wider type.

Python
print(5 + 2.5)    # Output: 7.5
print(5 + 2j)     # Output: (5+2j)
print(5 / 2)      # Output: 2.5
print(type(5 / 2))  # Output: <class 'float'>

This is why a calculation that starts with integers can end with a float. Once division happens, later arithmetic may stay in float form unless you convert back to int carefully.

Converting between numeric types

Python gives you built-in conversion functions for explicit changes. Use int() to drop the fractional part toward zero, float() to make a decimal number, and complex() to build a complex value.

Python
print(int(3.9))          # Output: 3
print(int(-3.9))         # Output: -3
print(float(4))         # Output: 4.0
print(complex(4))       # Output: (4+0j)

This conversion behavior matters because int() does not round; it truncates toward zero. That is a frequent source of off-by-one mistakes when people expect rounding instead of dropping the fraction.

How Numbers Work in Loops, Ranges, and Counting

Numbers show up constantly in loops. The range() function uses integers and is one of the most common places where beginners need to reason about number types and off-by-one behavior.

Python
for index in range(3):
    print(index)

# Output:
# 0
# 1
# 2

range(3) produces the integers 0, 1, and 2. The ending value is excluded, so the loop runs three times, not four. This matters any time you use a number to count items, pages, or indexes.

A lot of beginner bugs are not about the arithmetic itself. They come from forgetting whether a number is a count, an index, or a result of division.

How Number Formatting Differs from Number Storage

Printing a number and storing a number are not the same thing. Formatting changes how a number looks; it does not change the underlying value unless you assign the formatted result back as a different type. This is especially important with floats, where the stored value may contain more precision than you want to display.

Python
value = 12.34567

print(round(value, 2))   # Output: 12.35
print(value)              # Output: 12.34567

The rounded result is a new value for that expression. The original variable still holds the original float.

How Python Numbers Differ from Strings That Look Like Numbers

A string such as "42" is not a number, even though it contains digits. Python does not automatically convert strings into numeric types in arithmetic. You must convert the string first if you want numeric behavior.

Python
age_text = "21"
age = int(age_text)

print(age + 1)     # Output: 22

Without the conversion, Python would treat the value as text, not as a quantity. That difference matters everywhere you read user input or data from files.

Predict the Output

Read each snippet carefully and decide what Python prints before you open the answer.

Integer division and float division

Python
print(9 // 2)
print(9 / 2)

What does this print?

Show answer

// performs floor division and returns the integer part of the quotient, so the first line prints 4. The / operator always returns a float, so the second line prints 4.5.

Terminal
# Output:
# 4
# 4.5

Mixing int and float

Python
total = 5
total += 2.0
print(type(total))
print(total)

What happens?

Show answer

total starts as an int, but adding 2.0 promotes the result to float. The first line prints the float type, and the second line prints the decimal value.

Terminal
# Output:
# <class 'float'>
# 7.0

Common Mistakes with Python Numbers

Using / when you want an integer result

Beginners often expect / to keep a value whole when both inputs are whole numbers. In Python, that is not how it works.

Problem: This code produces a float, which can break code that expects an integer index or count.

Python
items = 10
pages = items / 3
print(pages)

Fix: Use // for floor division when you want an integer quotient.

Python
items = 10
pages = items // 3
print(pages)

The corrected version works because // returns the whole-number part of the division.

Comparing floats with ==

Float values can look equal when printed but still differ slightly in memory.

Problem: This comparison can fail because the two expressions may not produce exactly the same stored value.

Python
result = 0.1 + 0.2
print(result == 0.3)

Fix: Compare with a small tolerance using abs().

Python
result = 0.1 + 0.2
print(abs(result - 0.3) < 1e-9)

The fixed version works because it checks for a small acceptable difference instead of exact binary equality.

Using int() when you really need rounding

int() removes the fractional part rather than rounding to the nearest whole number.

Problem: This code truncates 9.9 to 9, which may be the wrong result if you wanted the nearest integer.

Python
score = 9.9
print(int(score))

Fix: Use round() when you want normal rounding.

Python
score = 9.9
print(round(score))

The corrected version works because round() chooses the nearest integer instead of dropping the fraction.

Find the Bug

Here is a small program that looks reasonable but gives the wrong result for one common beginner task. Find the bug before opening the answer.

Python
def average(numbers = [1, 2, 3]):
    return sum(numbers) // len(numbers)

print(average())

What is wrong with this code?

Show answer

The bug is //. Floor division throws away the decimal part, so the average of 1, 2, and 3 becomes 2 by luck, but many other inputs would be wrong. The function should use normal division so the result can be a float when needed.

Fixed code:

Python
def average(numbers = [1, 2, 3]):
    return sum(numbers) / len(numbers)

print(average())

The fixed version works because average values are often not whole numbers, so / preserves the fractional part.

When to Use int, float, and complex

Choose the type that matches the kind of number you really have. The wrong choice usually causes bugs later, not at the point where you first write the value.

Use this typeWhen it fitsExample
intCounting whole things, indexes, lengths, and exact whole-number math5, items[2]
floatMeasurements, averages, percentages, and decimal approximations3.14, temperature / 10
complexMathematics with real and imaginary parts2 + 3j

If you are writing ordinary business logic, int and float cover most needs. complex is specialized and appears much less often in beginner projects.

Interview Questions About Python Numbers

Why does / return a float even for two integers?

Because Python follows numeric semantics where true division always produces the mathematically correct quotient as a float when needed. If you want integer-style division, use //.

Why can two equal-looking floats compare as not equal?

Because floats are stored in binary approximation form. Some decimal values cannot be represented exactly, so tiny differences can appear after arithmetic.

When would you use complex numbers in real code?

Mainly in scientific and engineering code, especially signal processing, control systems, and formulas that naturally use an imaginary component. Most application code never needs them.

Try It Yourself

Write a short program that calculates the cost per item from a total price and item count.

  • Set total_price to 19.95.
  • Set item_count to 4.
  • Compute the price per item.
  • Print the result rounded to 2 decimal places.

Expected output:

Python
4.99

Hint: Use normal division to get a decimal result, then pass the value to round(..., 2).

Show solution
Python
total_price = 19.95
item_count = 4

price_per_item = total_price / item_count
print(round(price_per_item, 2))  # Output: 4.99

Summary

  • int stores exact whole numbers and is the best choice for counting and indexing.
  • float stores approximate decimal values and can show tiny rounding differences.
  • complex stores a real and imaginary part and uses j for the imaginary unit.
  • / returns a float, while // returns floor division.
  • Convert numeric types explicitly with int(), float(), and complex() when needed.
  • For a next topic, learn how Python handles strings and how text differs from numbers.