Doing math
Problem
The bill at the table
You ordered three coffees at €2.50 and two croissants at €1.50. You pay with a €20 bill. How much is the bill, and how much change should you get?
You can do it in your head. But the register at the café does this math hundreds of times a day, with different prices and quantities. The program has to do the math by itself.
The idea
The arithmetic operators
You do math the way you would on paper: + adds, - subtracts, * multiplies, / divides. These signs are called operators.
coffee = 2.5croissant = 1.5total = 3 * coffee + 2 * croissantchange = 20 - totalprint(f"Total: €{total}")print(f"Change: €{change}")Total: €10.5Change: €9.5The order is the same as in math: first * and /, then + and -. That is why 3 * coffee + 2 * croissant is 7.5 + 3. If you want a different order, you add parentheses: (2 + 3) * 4 is 20.
There is a fifth operator too, %. The next idea is about it.
More precisely, if you are curious
- Operators with the same precedence are evaluated left to right:
20 - 5 - 3is 12, not 18. -in front of a number makes it negative:-total.
- With text,
+does not add, it glues, but only text to text. Text + a number stops the program. That is the trap in the next card.
Try it
Concert tickets
Three tickets at €8 and a €5 order fee.
What will the program print?
tickets = 3fee = 5print("Total: " + tickets * 8 + fee)* is done first: tickets * 8 is 24. Then left to right: "Total: " + 24 is text + a number, and Python stops: TypeError: can only concatenate str (not "int") to str. With an f-string the math is inside the curly braces and you get 29: f"Total: {tickets * 8 + fee}".Problem
2.25 hours instead of 2 h 15 min
The movie is 135 minutes long. You want to show it as hours and minutes: 2 h 15 min. The first try:
minutes = 135hours = minutes / 60print(f"{hours} h")2.25 hIn Python, / always gives a decimal result, even when both numbers are whole: 6 / 3 is 2.0, and 17 / 3 is 5.666666666666667. But here you need two whole hours and the minutes that are left. How do you get only the whole part?
The idea
Integer division: // and %
// divides and keeps only the whole part: 135 // 60 is 2, and 17 // 3 is 5. The decimal part is cut off. This is called integer division.
Here it is step by step, with the sum of three grades:
math = 5physics = 6english = 6whole = (math + physics + english) // 3print(f"Whole part: {whole}")Step by step, in words
- Three grades, each in an int: 5, 6, 6.
- First the parentheses: 5 + 6 + 6 = 17. The sum is an int too.
- 17 // 3: how many whole groups of 3 are in 17? 5.
- The remainder 2 (that is 17 % 3) is cut off. The result is the whole number 5.
- 5 is stored in whole. The result of // on whole numbers is an int, with no .0.
- It prints "Whole part: 5". The decimal part (5.67) is not in the result: that is what / is for.
What is cut off is not completely lost. The % operator gives the remainder of the division: 17 % 3 is 2, because 17 = 5 · 3 + 2.
Together the two split an amount into whole parts and a remainder. The movie is 135 minutes:
minutes = 135hours = minutes // 60rest = minutes % 60print(f"{hours} h {rest} min")2 h 15 minYou will need % often. A number is even if n % 2 is 0. The last digit of a number is n % 10.
More precisely, if you are curious
- With negative numbers
//rounds down, toward the smaller number:-7 // 2is -4, not -3 as in Java and C#. The remainder has the sign of the divisor.%also works with decimal numbers:
print(-7 // 2)print(-7 % 2)print(7.5 % 2)-411.5- Division by 0 stops the program:
ZeroDivisionError: division by zero. In Python this is true for decimal numbers too:5.0 / 0also stops.
Try it
Bottles in cases
A case holds 6 bottles. You have 17.
What will the program print?
bottles = 17per_case = 6print(f"{bottles // per_case} cases")print(f"{bottles % per_case} left over")17 // 6 is 2 whole cases (12 bottles), and 17 % 6 is the remainder: 5 bottles that do not fill a case.
The idea
Converting between types
In Python / already gives a decimal result, and the average grade comes out right away. You need a conversion the other way: from decimal to whole.
total = 5 + 6 + 6average = total / 3print(average)print(f"{average:.2f}")whole = int(9.99)print(whole)5.6666666666666675.679You convert a type by writing the name of the type: int(9.99) makes an int, and float(17) makes 17.0. This is called a cast. int(...) cuts off the decimal part: int(9.99) is 9, not 10.
From int to float nothing is lost, and the conversion happens by itself: 10 + 0.5 is a float, 10.5. If one side is a float, // also gives a float: 17 // 3.0 is 5.0.
More precisely, if you are curious
int("25")from the lesson on input is the same function: it turns both text and a decimal number into a whole number.- Every character has a code, a number in the character table.
ordgives the code, andchrmakes a character from a code:
print(ord("A"))print(chr(66))max_int = 2147483647print(max_int + 1)65B2147483648- In Java and C#,
intgoes up to 2,147,483,647, and one more "wraps around" to a negative number. In Pythoninthas no limit, so the third line simply gives 2147483648.
Try it
Find the bug
The electricity bill is €125, split between three roommates. The program says each person pays €41.00, but it should be €41.67. Which line is the bug on?
Pick the line with the bug.
// is integer division: 125 // 3 is 41, and the decimal part is cut off. The .2f format then shows 41 as 41.00. For decimal division it is /: share = bill / people.The idea
Shorthand: += and -=
You often change a value based on itself: the card balance goes down with every purchase, a counter goes up by one. There is a short way to write this:
balance = 20purchases = 0balance -= 4.5purchases += 1balance -= 3.5purchases += 1print(f"{purchases} purchases, €{balance} left")2 purchases, €12.0 left| You write | It means |
|---|---|
balance -= 4.5 |
balance = balance - 4.5 |
total += price |
total = total + price |
x *= 2, x /= 2, x //= 2, x %= 2 |
the same with *, /, // and % |
purchases += 1 |
purchases = purchases + 1 |
seats -= 1 |
seats = seats - 1 |
Python has no ++ and --. A counter goes up with += 1.
+= works with text too: message += "!" glues an exclamation mark onto the end.
More precisely, if you are curious
a++ in Python is SyntaxError: invalid syntax. ++a is sneakier: it is not an error, but two plus signs in front of the number, +(+a). The value does not change:
a = 5++aprint(a)5If you come from another language, be careful: the counter stays the same, and Python says nothing.
The idea
math: roots, powers, rounding
A pizza place sells a 30 cm pizza for the same price as two 20 cm pizzas. Which is more? The area of a circle is π · r². For powers Python has an operator: **. 15 ** 2 is 225. For π and for the square root there is something ready in the math module: the line import math at the top loads it, and then you write math., the name and the numbers in parentheses. These are functions, ready-made pieces of code. You will write your own in the "Functions" module.
import math
big = math.pi * 15 ** 2small = 2 * math.pi * 10 ** 2print(f"One 30 cm pizza: {big:.1f} sq cm")print(f"Two 20 cm pizzas: {small:.1f} sq cm")print(math.sqrt(144))print(abs(-7.5))One 30 cm pizza: 706.9 sq cmTwo 20 cm pizzas: 628.3 sq cm12.07.5One big pizza is more than two small ones.
| You write | What it gives |
|---|---|
math.sqrt(x) |
the square root |
x ** n or math.pow(x, n) |
x to the power n |
abs(x) |
the absolute value (without the sign), no math. |
round(x) |
rounding to a whole number, no math. |
math.pi |
the number π, 3.14159… |
math.sqrt and math.pow return a float, even when the result is a whole number (that is why you see 12.0). ** with whole numbers gives an int: 15 ** 2 is 225. If you need an int, convert it: int(math.sqrt(144)).
More precisely, if you are curious
- Rounding 2.5: the languages give different results.
print(round(2.5))print(round(3.5))print(round(5.678, 2))245.68roundrounds "the half" to the even number: 2.5 becomes 2, and 3.5 becomes 4. Banks do it this way (hence the name "banker's rounding"), and so does C#. With a second argument you round to that many digits after the decimal point:round(5.678, 2)is 5.68.
- f-strings do not follow the computer's language settings: a point stays a point everywhere.
Exercise
Let the program do the math
Solve the tasks in your editor. Each number in the input is on a separate line.
1. Average of three numbers. Read three whole numbers and print their average with two digits after the decimal point. Here you need decimal division.
566Average: 5.672. Seconds into hours. Read a number of seconds and split it into hours, minutes and seconds. Hint: an hour has 3600 seconds, and % gives what is left.
37251 h 2 min 5 s3. Volume of a sphere. Read the radius and print the volume: V = 4/3 · π · r³. Here 4 / 3 is 1.333…, as it should be. But what would 4 // 3 be?
10Volume: 4188.79 cubic cm4. Celsius to Fahrenheit. F = C · 9 / 5 + 32. Read the temperature in degrees Celsius.
3737.0 °C = 98.6 °FMore tasks
- Inches to centimeters. One inch is 2.54 cm. For 12 inches:
30.48 cm. - Area of a rectangle. Read the length and the width, and print the area (length · width).
- Area of a square. Read the side and print the area. Do it once with
*and once with**. - Radians to degrees. Degrees = radians · 180 / π. For 3.14159:
180.00°. - Hours to seconds. Read a number of hours and print how many seconds that is. For 2 hours: 7200.
- A character's code. Read a character and print its code. For
A: 65. You get the first character of the text you read withinput()[0]. You will see what this means in the lesson on text.
Test