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:
| Operator | Name | Returns | Example |
|---|---|---|---|
/ | True division | Always float | 10 / 2 produces 5.0 |
// | Floor division | int (when both operands are int) | 10 // 3 produces 3 |
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.
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
| Expression | Value | Type | Rule |
|---|---|---|---|
10 + 3 | 13 | int | int + int = int |
10 + 3.0 | 13.0 | float | int + float = float |
10 / 2 | 5.0 | float | / always returns float |
10 // 3 | 3 | int | // 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 returnsfloatint + float = float//returnsint(when both operands areint)
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:
- Change
10 + 3to10 + 3.5. What is the value? What is the type? - Change
10 / 2to10 // 2. What is the value? What is the type? - Change
10 // 3to10.0 // 3. What is the value? What is the type?
Check your modifications
10 + 3.5=13.5, typefloat(int + float = float)10 // 2=5, typeint(floor division of two ints = int)10.0 // 3=3.0, typefloat(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.
-
"A book has 45,000 words. At 250 words per minute, how many minutes to read it?"
-
"A box holds 12 items. You have 50 items. How many full boxes do you need?"
-
"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.
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
-
Seven operators cover all basic arithmetic:
+,-,*,/,//,%,**. The first four are familiar; the last three (//,%,**) are new. -
Division always returns float.
10 / 2produces5.0, not5. Use//when you need an integer result. -
Mixed types promote to float. Any expression with at least one
floatoperand produces afloatresult. The only exception://with twointoperands returnsint. -
round()controls precision. Useround(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.