Command Palette

Search for a command to run...

Hectal
PHASE 1Beginner ~26 min· topic 7 of 11

Topic 1.7

Arithmetic, Precedence and Augmented Assignment

In one line

Python follows a fixed order of operations (precedence): powers first, then multiplication and division, then addition and subtraction. Use parentheses to be clear, use += and friends to update a variable, and reach for the math module and built-ins like abs, min and max for more.

Think of it like this

Reading a shopping bill. "2 packets at 10 rupees plus 5 rupees delivery" means 2 x 10 + 5 = 25, because multiplication happens before addition. Everyone agrees on the order, so no one asks. Python has the same agreement, called operator precedence: some operators go first, regardless of how you read left to right.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Operator
A symbol that does an operation, like + or **.
Operand
A value an operator works on. In 3 + 4, the 3 and the 4.
Precedence
The order in which operators run when a line has several.
Associativity
Which way operators of the same level group: left to right, or (for **) right to left.
Augmented assignment
An update such as x += 1, short for x = x + 1.
Unary minus
A minus sign in front of one value, like -x.
math module
A standard-library module of maths functions such as sqrt and floor.
Built-in function
A function available everywhere without import, such as abs, min, max.

Step by step

01Multiplication before addition

Python's calculator rules match school maths. 2 + 3 * 4 is 2 + 12, which is 14. To add first, use parentheses.

main.pywhole filepython
print(2 + 3 * 4)       # 14
print((2 + 3) * 4)     # 20

02The power surprises

Read -3 ** 2 as "minus (three squared)": the power runs first, and the minus is applied to the result. That gives -9. With parentheses, (-3) ** 2 is 9.

For 2 ** 3 ** 2 Python works from the right: 3 ** 2 is 9, then 2 ** 9 is 512. This matches maths, where a tower of powers is read from the top down.

main.pywhole filepython
print(-3 ** 2, (-3) ** 2)           # -9 9
print(2 ** 3 ** 2, (2 ** 3) ** 2)   # 512 64
The power surprisesdiagram
Rendering diagram…

03Same level goes left to right

10 - 4 - 3 groups as (10 - 4) - 3. Likewise 100 / 10 / 5 is (100 / 10) / 5, which is 2.0. Only ** groups the other way.

main.pywhole filepython
print(10 - 4 - 3, 100 / 10 / 5)     # 3 2.0
print(7 // 2 * 2 + 7 % 2)            # 7

04Update a variable: +=

A score that grows is the most common use of +=. Each augmented assignment reads the old value, works it out, and rebinds the name. After score /= 4 the type changed from int to float, because / always gives a float.

main.pywhole filepython
score = 10
score += 5       # 15
score -= 3       # 12
score *= 2       # 24
score /= 4       # 6.0
score **= 2      # 36.0
print(score)

05Built-ins and the math module

import math makes the module available, and you write math.sqrt(16). Constants such as math.pi have no brackets because they are values, not functions.

math.sqrt(2) and 2 ** 0.5 give the same float. Use math.sqrt for clarity and ** for general roots.

In the last line, math.gcd(12, 18) is the biggest whole number that divides both (6). math.factorial(5) is 5 x 4 x 3 x 2 x 1 (120). math.hypot(3, 4) is the length of the long side of a right-angled triangle whose short sides are 3 and 4 (5.0).

main.pywhole filepython
import math
print(math.sqrt(16), math.pi)
print(abs(-7), max(3, 9, 5), min(3, 9, 5))
print(math.gcd(12, 18), math.factorial(5), math.hypot(3, 4))

06Four ways to remove a fraction

For -2.5: math.floor gives -3 (down), math.ceil gives -2 (up), math.trunc gives -2 (towards zero), round gives -2 (nearest even). Know which one you mean: they only agree on whole numbers.

main.pywhole filepython
import math
print(math.floor(-2.5), math.ceil(-2.5), math.trunc(-2.5), round(-2.5))
# -3 -2 -2 -2

Try it yourself

  1. 1

    Predict, then run

    Predict 8 - 2 * 3 ** 2. Work it out on paper: power, then multiply, then subtract. Then run it.

  2. 2

    Average of three marks

    With a = 70, b = 85, c = 90, compute the average. First write it wrongly as a + b + c / 3 and see the result, then add the parentheses it needs.

  3. 3

    Update in steps

    Start with balance = 100. Use += to add 50, *= to double it, and -= to take away 30. Print after each step.

Code & diagrams

Precedence and augmented assignment New tab

Before running, write down your prediction for each of the first five lines.

Sign in to run this example in your browser.

Expected output

14 20
-9 9
512 64
3 2.0
7
True True
15
12
24
6.0
36.0
3
1
Built-ins and the math module New tab

Compare floor, ceil, trunc and round for -2.5 on line 4.

Sign in to run this example in your browser.

Expected output

4.0 3.141592653589793 2.718281828459045
-3 -2 -2 -2
2 3
7 9 3 1024 0.5
6 120 5.0
10.0 3.0
1.4142135623730951 1.4142135623730951
Precedence ladderdiagram
Rendering diagram…

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Square root of a negative number

Ask math.sqrt for the square root of -1.

main.pywhole filepython
import math

print(math.sqrt(-1))
terminal
$ python main.py
── what you'll see ──
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(math.sqrt(-1))
~~~~~~~~~^^^^
ValueError: math domain error

Break #2

Update a variable that does not exist

Use += on a name that was never created.

main.pywhole filepython
points += 1
terminal
$ python main.py
── what you'll see ──
Traceback (most recent call last):
File "main.py", line 1, in <module>
points += 1
^^^^^^
NameError: name 'points' is not defined. Did you mean: 'print'?

Myth vs fact

Myth

-3 ** 2 is 9.

Fact

** runs before the unary minus, so it is -(3 ** 2), which is -9. Write (-3) ** 2 for 9.

Myth

2 ** 3 ** 2 is 64.

Fact

Powers group from the right: 2 ** (3 ** 2) is 512.

Myth

x += 1 and x = x + 1 are always identical.

Fact

For numbers they are. For lists (Phase 4) += changes the list in place, while x = x + [..] builds a new one, and that difference matters.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The full precedence table in Python has about 18 levels. From tightest to loosest: **, unary + - ~, * / // % @, + -, shifts << >>, &, ^, |, comparisons and in/is, not, and, or, the conditional expression, lambda, then :=. Two consequences interviewers test: 1 + 2 << 3 is (1 + 2) << 3 (24), and, unlike C, x & 1 == 0 means (x & 1) == 0 because comparisons are looser than &. You do not need to memorise it: use parentheses wherever you doubt.

  • ▸

    ** has a few more rules. It binds tighter than a unary operator on its left (-3 ** 2 is -9) but a unary operator on its right is fine (2 ** -1 is 0.5). A negative base with a fractional exponent gives a complex number, not an error: (-8) ** (1 / 3) is (1.0000000000000002+1.7320508075688772j). 0 ** 0 is 1, and 0.0 ** -1 raises ZeroDivisionError. For big modular powers use the three-argument pow(base, exp, mod), which never builds the huge intermediate number (used in cryptography).

  • ▸

    Operators call special methods: a + b calls a.__add__(b), and if that returns NotImplemented Python tries b.__radd__(a). That is why + works on numbers, strings and lists, and why NumPy arrays can add element by element (Phase 8 and Phase 14). For x += y Python tries __iadd__ first: lists define it (in-place, same object), ints and strings do not, so they fall back to x = x + y. In a[i] += 1 the target a[i] is evaluated once.

  • ▸

    Since Python 3.8 math.dist, math.prod, math.isqrt (exact integer square root) and math.comb exist. math.isqrt is the safe choice for big ints, where math.sqrt would round to a float: math.isqrt(10 ** 40) is exact. Python 3.9 added math.lcm.

  • ▸

    Machine learning code does a lot of arithmetic on whole arrays. NumPy runs a * b + c on millions of numbers in compiled code, with the same precedence rules as here.

Remember this

  1. 1

    From strongest (first) to weakest (last), the arithmetic order is: ** (power); unary minus -x; then *, /, //, %; then + and -. Comparisons (<, ==) come after all arithmetic (Topic 1.8). Operators on the same level run left to right, so 10 - 4 - 3 is (10 - 4) - 3, which is 3, not 9.

  2. 2

    Parentheses override everything. (2 + 3) * 4 is 20 while 2 + 3 * 4 is 14. When a line is hard to read, add parentheses even if the precedence rules would give the same answer. Clear code beats clever code.

  3. 3

    Two surprises. First, ** is right-associative: 2 ** 3 ** 2 is 2 ** (3 ** 2), which is 512, not 64. Second, ** binds tighter than a minus sign on its left: -3 ** 2 is -(3 ** 2), which is -9. To square minus three, write (-3) ** 2.

  4. 4

    Augmented assignment updates a variable using its old value. score += 5 means score = score + 5. The family: +=, -=, *=, /=, //=, %=, **=. They are shorter, and they put the name on the line only once, which avoids typos. Note that the variable must exist first: points += 1 on a new name gives NameError.

  5. 5

    Python has built-in helpers for numbers: abs(x) (distance from zero), min(a, b, ...), max(a, b, ...), pow(a, b) and round(x). The math module (a ready-made toolbox of functions) adds sqrt, floor, ceil, trunc, gcd, factorial, hypot, log2, log10 and the constants math.pi and math.e. You load the module with import math (Topic 6.1).

  6. 6

    math.floor goes toward minus infinity, math.ceil toward plus infinity, math.trunc toward zero, and round to the nearest even. For -2.5 they give -3, -2, -2 and -2. Most functions in math return floats, so math.sqrt(16) is 4.0. (floor, ceil, trunc, gcd and factorial return ints.) They raise ValueError for impossible input (math.sqrt(-1)).

Explain it without notes

01

State the order of operations for +, -, *, /, //, % and ** in Python.

02

Why is -3 ** 2 equal to -9, and what is 2 ** 3 ** 2?

03

What does x += 1 do, and when does it fail?

04

How do floor, ceil, trunc and round differ on -2.5?

Practice

01

Compute and print the average of the marks 72, 88 and 95, rounded to 2 decimal places.

02

Start with count = 3, then use augmented assignment to double it and then add 10. Print count.

03

Print the longest side (the hypotenuse) of a right triangle with sides 6 and 8, using the math module.

Trade-offs

  • ↔

    Relying on precedence vs. adding parentheses. The rules are reliable, but extra parentheses cost nothing and save the next reader a pause. Use them when a line mixes more than two kinds of operator.

  • ↔

    **** vs. math.sqrt/math.pow.** ** works with ints exactly (2 ** 100); math.sqrt, math.pow and friends return floats and can lose precision on big ints. Use each for what it is good at.

Done when you can

  • Done when you can evaluate 2 + 3 * 4 ** 2 by hand and check it in Python.

  • Done when you can explain -3 ** 2 and 2 ** 3 ** 2.

  • Done when you can use +=, -=, *= and //= and know the variable must exist first.

  • Done when you can use abs, min, max and math.sqrt.

  • Done when you can choose between floor, ceil, trunc and round.