Skip to main content

Arithmetic and Number Types

In Lesson 1, you wrote typed variables: age: int = 30, price: float = 9.99. Now you will combine those variables with arithmetic operators to compute new values. Along the way, you will discover something that surprises every beginner: dividing two integers does not always give you an integer.

Seven Operators

Python gives you seven arithmetic operators. Four are familiar from school math. Three are new.

# Familiar operators
total: int = 10 + 3 # 13 (addition)
diff: int = 10 - 3 # 7 (subtraction)
product: int = 10 * 3 # 30 (multiplication)
quotient: float = 10 / 3 # 3.333... (division, always float!)

# New operators
floored: int = 10 // 3 # 3 (floor division, whole number only)
remainder: int = 10 % 3 # 1 (modulo, what's left over)
power: int = 2 ** 10 # 1024 (exponentiation, 2 to the 10th)

Output:

13
7
30
3.3333333333333335
3
1
1024

The first three work as you expect. Division is where it gets interesting.


The Division Surprise

James writes a SmartNotes calculation: how many minutes to read 1,500 words at 250 words per minute?

words: int = 1500
words_per_minute: int = 250
reading_time: float = words / words_per_minute
print(reading_time)

Output:

6.0

He expected 6. He got 6.0. "Why is it a float? I divided two integers!"

Emma asks him to check the type:

print(type(words / words_per_minute))

Output:

<class 'float'>

"In Python, / always returns a float," Emma explains. "Even when the result is a whole number. That is how the language works."

James tries the other division:

reading_time_int: int = words // words_per_minute
print(reading_time_int)
print(type(reading_time_int))

Output:

6
<class 'int'>

"Wait, so there are two kinds of division?" James asks.

Emma nods. "One (/) always gives the full decimal answer. The other (//) gives only the whole number part, dropping everything after the decimal point."

Here is the rule:

OperatorNameReturnsExample
/True divisionAlways float10 / 2 produces 5.0
//Floor divisionint (when both operands are int)10 // 3 produces 3
If you're new to programming

Division in Python always gives you a decimal number (float). If you want a whole number, use // (floor division). Think of it as "how many times does it fit completely?" For example, 17 // 5 asks: "How many complete groups of 5 fit into 17?" Answer: 3 (with 2 left over).


Remainder and Exponentiation

The remaining two operators complete your toolkit.

Modulo (%) gives the remainder after division. It answers "what is left over?"

leftover: int = 17 % 5
print(leftover)

Output:

2

17 divided by 5 is 3 with a remainder of 2. Floor division (//) gives the 3. Modulo (%) gives the 2. They are partners.

Exponentiation (**) raises a number to a power.

squared: int = 3 ** 2
print(squared)

cubed: int = 3 ** 3
print(cubed)

Output:

9
27

3 ** 2 means 3 multiplied by itself: 3 x 3 = 9. 3 ** 3 means 3 x 3 x 3 = 27.


Mixed Types: int + float = float

When you mix int and float in a single expression, Python promotes the result to float. This is called type promotion.

total_items: int = 10
price_per_item: float = 4.99
total_price: float = total_items * price_per_item
print(total_price)
print(type(total_price))

Output:

49.9
<class 'float'>

The rule: if any operand is float, the result is float.

# int + int = int
result_a: int = 10 + 3
print(result_a, type(result_a))

# int + float = float
result_b: float = 10 + 3.0
print(result_b, type(result_b))

# int / int = float (always!)
result_c: float = 10 / 2
print(result_c, type(result_c))

# int // int = int
result_d: int = 10 // 3
print(result_d, type(result_d))

Output:

13 <class 'int'>
13.0 <class 'float'>
5.0 <class 'float'>
3 <class 'int'>

Precision Control with round()

Sometimes you need fewer decimal places. The built-in round() function controls precision.

pi: float = 3.14159
rounded_pi: float = round(pi, 2)
print(rounded_pi)

total: float = 10 * 4.99
rounded_total: float = round(total, 2)
print(rounded_total)

Output:

3.14
49.9

round(value, digits) takes two arguments: the number to round and how many decimal places to keep. round(3.14159, 2) keeps two decimal places, giving 3.14.

SmartNotes Connection

When you build SmartNotes functions later in this chapter, you will use round() to display clean reading times. A reading time of 1.4285714285714286 minutes is not helpful to a user; round(reading_time, 1) gives 1.4.


PRIMM-AI+ Practice: Predicting Types and Values

Predict [AI-FREE]

For each expression below, predict both the value and the type (int or float). Write your predictions and a confidence score from 1 to 5 before checking the answers.

# Expression 1
10 + 3

# Expression 2
10 + 3.0

# Expression 3
10 / 2

# Expression 4
10 // 3
Check your predictions
ExpressionValueTypeRule
10 + 313intint + int = int
10 + 3.013.0floatint + float = float
10 / 25.0float/ always returns float
10 // 33int// returns int when both operands are int

If you got all four correct with confidence 4-5, the type rules are solid. If you missed Expression 3 (predicted 5 instead of 5.0), remember: / always returns float, even when the answer is a whole number.

Run

Type these four expressions into your Python environment (or Claude Code) and compare the output to your predictions.

Run these four expressions in Python and show the result and type of each:
10 + 3
10 + 3.0
10 / 2
10 // 3

Investigate

For any prediction you got wrong, write down which rule you missed:

  • / always returns float
  • int + float = float
  • // returns int (when both operands are int)

Identifying the rule you missed is more valuable than getting the answer right by luck.

Modify

Change one operand in each expression and predict the new result and type:

  1. Change 10 + 3 to 10 + 3.5. What is the value? What is the type?
  2. Change 10 / 2 to 10 // 2. What is the value? What is the type?
  3. Change 10 // 3 to 10.0 // 3. What is the value? What is the type?
Check your modifications
  1. 10 + 3.5 = 13.5, type float (int + float = float)
  2. 10 // 2 = 5, type int (floor division of two ints = int)
  3. 10.0 // 3 = 3.0, type float (one operand is float, so result is float, even with //)

If modification 3 surprised you: // still does floor division, but when one operand is float, the result is float. The value is 3.0, not 3.

Make [Mastery Gate]

Write the typed expression that computes the answer for each word problem. Include the type annotation on the variable.

  1. "A book has 45,000 words. At 250 words per minute, how many minutes to read it?"

  2. "A box holds 12 items. You have 50 items. How many full boxes do you need?"

  3. "After filling full boxes, how many items are left over?"

Check your expressions
# Problem 1: reading time (use / because we want the precise decimal answer)
word_count: int = 45000
wpm: int = 250
reading_minutes: float = word_count / wpm # 180.0

# Problem 2: full boxes (use // because we want whole boxes only)
items_per_box: int = 12
total_items: int = 50
full_boxes: int = total_items // items_per_box # 4

# Problem 3: leftover items (use % because we want the remainder)
leftover: int = total_items % items_per_box # 2

Notice the operator choice: / for a precise answer, // for "how many complete groups," and % for "what is left over." Each operator answers a different question.

Dual-track for experienced programmers

Python 3 changed / to true division (always float). Python 2's / performed integer division for int operands. If you remember Python 2 behavior, // is the explicit equivalent. Try -7 // 2 and predict whether the result is -3 or -4. (Hint: floor division rounds toward negative infinity, not toward zero. The answer is -4.)


Try With AI

Open Claude Code in your SmartNotes project and try these prompts.

Prompt 1: Check the Type Rules

I'm learning Python arithmetic. Here are my rules:
1. int + int = int
2. int + float = float
3. int / int = float (always)
4. int // int = int

Are these correct? Are there any edge cases I should know about?

Read AI's response. Did it confirm all four rules? Did it mention what happens when you use // with a float operand (like 10.0 // 3)? Compare its answer to what you learned in this lesson.

What you're learning: You are testing your mental model against AI's knowledge, identifying gaps before they cause bugs in your specifications.

Prompt 2: Generate a Calculation

Write a Python expression that calculates how many full weeks
and leftover days are in 100 days. Use // for full weeks and
% for leftover days. Add type annotations to every variable.

Read the output. Predict: what values will full_weeks and leftover_days have? Check by running the code.

What you're learning: You are reading AI-generated arithmetic expressions and verifying them mentally, the same skill you will use when AI generates function bodies in your TDG cycles.


Key Takeaways

  1. Seven operators cover all basic arithmetic: +, -, *, /, //, %, **. The first four are familiar; the last three (//, %, **) are new.

  2. Division always returns float. 10 / 2 produces 5.0, not 5. Use // when you need an integer result.

  3. Mixed types promote to float. Any expression with at least one float operand produces a float result. The only exception: // with two int operands returns int.

  4. round() controls precision. Use round(value, digits) to keep a specific number of decimal places.


Looking Ahead

You can write typed variables (Lesson 1) and compute new values from them (this lesson). In Lesson 3, you will compare values using ==, !=, <, >, <=, and >=. These comparison operators produce bool results: True or False. Combined with and, or, and not, they let you express conditions like "is the reading time under 5 minutes AND is the note not a draft?" That is the last piece before you can write complete function specifications.