Why this matters
Almost every program does arithmetic. A shop adds up a bill, a game moves a character by a speed, a clock turns 135 minutes into hours and minutes, and a website splits 53 search results into pages of 10. Each of these is a small piece of arithmetic, and each one can go wrong in a way that is hard to see.
Python arithmetic has three traps that beginners fall into again and again. The // operator throws away the part after the decimal point, and it is easy to use it when you meant the other division. The remainder operator % follows a sign rule that is different from many other languages. Decimal numbers stored as float are close approximations, so a simple sum can print a value like 0.30000000000000004. Interview questions use all three. By the end of this lesson you will know each trap, see it happen in a running program, and know how to avoid it.
If you already know another language, note that Python integers never overflow by default. The overflow section below explains this, and when a fixed-size integer does matter.
Start from the first principle: values, operators and types
A value is a piece of data a program works with, such as the number 7 or the text "hello". An operator is a symbol that does something to values. The values an operator works on are its operands. In the statement 3 + 4, the + is the operator and 3 and 4 are the two operands.
A group of operators and operands that produces one value is called an expression. 3 + 4 is an expression. Its value is 7. You can put an expression anywhere a value is allowed: inside a call to print, on the right side of =, or inside another expression.
Every value in Python has a type. The type tells Python which operations make sense for the value. You can check it with the type function:
The output is:
<class 'int'>
<class 'float'>
<class 'str'>These are the number types you need in this lesson:
intstores a whole number. Python has no fixed upper limit for it, sointcan hold numbers with hundreds of digits.floatstores a number with a decimal point, such as3.5. It is an approximation, and the floats section below explains why.boolstoresTrueorFalse. It is a kind of whole number too, whereTruecounts as 1 andFalsecounts as 0.
A variable is a name that points at a value. You create one by writing the name, then =, then the value. Python does not ask you to declare the type first. The value decides the type, and a name can later point at a value of a different type.
The type of an operation depends on the types of its operands. Two int values give an int result for +, -, *, //, % and ** (for a non-negative exponent). Division with / always gives a float, even when both operands are int. The division section below shows this in detail, because it is the first thing to remember.
What the computer does with your numbers
You do not need to think in bits every day, but a little of the machine helps explain the surprises in this lesson.
Inside the computer, every value is a row of bits. A bit is a single binary digit, either 0 or 1. A Python int is stored in as many bits as it needs. Small numbers take a few bits and very large numbers take more, so an int grows as needed. A float uses 64 bits, and the bits are split into parts for the sign, the size and the digits of the number.
The float format stores numbers in base 2, not base 10. In base 2 the decimal number 0.1 has no finite form. Its binary digits repeat forever, so the computer stores the closest value it can fit in 64 bits. That stored value is not exactly 0.1. The decimal standard module can show the exact value that is stored, and you will see it in the floats section below.
Keep two facts in mind. Python int values never wrap around by themselves. Python float values are close approximations of decimal numbers. Most of the rules in the rest of this lesson follow from those two facts.
The seven operators
The operators for numbers are shown below with examples that use the operands 7 and 2.
| Operator | Name | Example | Result |
|---|---|---|---|
+ | addition | 7 + 2 | 9 |
- | subtraction | 7 - 2 | 5 |
* | multiplication | 7 * 2 | 14 |
/ | true division | 7 / 2 | 3.5 |
// | floor division | 7 // 2 | 3 |
% | remainder (also called modulus) | 7 % 2 | 1 |
** | power | 7 ** 2 | 49 |
The first three work the way they do in school maths. The last four need care, and most of this lesson is about them.
Here is a complete program that uses the operators on two variables. The names are apples and bags, so the program reads like the sentence it does. Read it line by line and predict the output before you look at it.
The output is:
total: 9
difference: 5
product: 14
quotient: 3.5
floor quotient: 3
remainder: 1
power: 49The line f"total: {total}" is an f-string. The letter f before the quote tells Python to put the value of each name inside the braces into the text. You can put any expression inside the braces, for example f"{a + b}". F-strings are the usual way to build output text in Python.
The name total is used instead of sum. sum is the name of a built-in function. You can reuse it as a variable name, but then the function is hidden for the rest of the program, which causes confusing errors. Choose names that do not match built-in names such as sum, max, min, list or str.
Division: / gives a decimal, // drops the part after the point
Think about sharing 7 biscuits between 2 children. Each child gets 3 whole biscuits, and one biscuit is left over. The // operator gives you the 3 each child gets, and the % operator gives you the 1 left over. Together they split a number into whole groups and the remainder. The / operator gives the exact answer, 3.5 biscuits each, which is what you want when you measure something rather than share it in whole pieces.
Python has two division operators, and the names are easy to mix up:
/is true division. It always returns afloat, even when both operands are whole numbers.7 / 2is3.5, and8 / 2is4.0.//is floor division. It returns the result rounded down to the nearest whole number.7 // 2is3. The word "floor" means "round toward negative infinity", so the rounding goes down for negative results too. You will see this in the negative numbers section below.
Run this program and predict each line first:
The output is:
a / b: 3.5
a // b: 3
float(a) / b: 3.5
int(a / b): 3
average with //: 4
average with /: 4.5Each line teaches one part of the rule.
The first line is /, which gives the decimal result 3.5. Python does not cut the decimal part off here.
The second line is //, which gives 3. This is the operator that drops the part after the point.
The third line uses float(a). The function float turns a value into a float. Here it is not needed, because / already gives a decimal result. It shows that a decimal result can be made from an int on purpose.
The fourth line uses int(a / b). The function int turns a value into a whole number by cutting the decimal part off toward zero. It gives 3, the same as // for positive numbers. It is different for negative numbers, and you will see the difference below.
The fifth line is the classic average trap. (a + b) // 2 is 9 // 2, which is 4. The average is 4.5, so this line is wrong for an average. The problem is the operator, not the value. Use / when you want the decimal answer.
The sixth line is the fix. (a + b) / 2 gives 4.5.
A rule of thumb follows from this. Use / when you measure, average or divide money. Use // when you count whole groups, pages or boxes.
A picture of the split
Picture 7 items laid out in rows of 2. You can make three full rows, and one item is left over. Three is what // returns, and one is what % returns. Read the picture as the answer to two questions. How many full groups? That is //. How many are left? That is %.
The remainder operator
The % operator gives what is left after floor division. Mathematicians often call it modulus, and many people say "mod" for short. For positive numbers the meaning is simple:
This prints 1 and then 0. Ten split into groups of three leaves one. Eight split into groups of four leaves nothing.
The most useful identity to remember is this:
a == (a // b) * b + a % b
It holds for every integer a and every non-zero integer b. It is the reason // and % belong together. If you know the quotient and the remainder, you can rebuild the original number.
What happens with negative numbers
Negative numbers are where Python differs from many other languages. The rule is simple. Python chooses the quotient (the whole-number result of the division) so that it is rounded down, and the remainder then takes the sign of the right operand, the divisor.
Run this program and check the rule:
The output is:
-4
1
-1
0
-7The first line is -7 // 2. The exact answer is -3.5, and floor division rounds down, so the result is -4, not -3. Some people expect -3 because they think of cutting toward zero. Python does not do that.
The second line is -7 % 2, which is 1. The remainder has the sign of the divisor 2, which is positive, so the result is positive.
The third line is 7 % -2, which is -1. The divisor is negative, so the remainder is negative.
The fourth line is -8 % 4, which is 0. A remainder of zero means the number divides evenly, even when it is negative.
The last line checks the identity. (-4) * 2 + 1 is -7, so the identity holds.
This matters for the test for an odd number. In Python, n % 2 == 1 works for negative numbers too, because -3 % 2 is 1. Here is the same check in a few lines:
The output is:
4 False False
7 True True
-3 True True
-4 False FalseThe test n % 2 != 0 is also correct in Python, so you can use either form. If you write the same test in a language where the remainder of a negative number is negative, the == 1 form fails. Use != 0 in that case, because it works for both signs.
Three everyday uses of the remainder
The remainder appears in more programs than you might expect. Here are three uses that show up in interview questions and in real code.
- Even and odd.
n % 2 == 0is true for even numbers. Use!= 0when you want the odd numbers. - The last digit.
n % 10gives the final digit of a whole number. For 4825 it gives 5. Floor division by 10 removes that digit:4825 // 10is 482. - Wrapping around. When you have
sizeslots in a circle and you move forward one slot,(index + 1) % sizebrings you back to 0 after the last slot. This pattern appears in circular queues and in games that loop through players.
The next program uses the last-digit trick on a four-digit number. The number is written in the program, so there is no input step.
The output is:
digit sum: 19
reversed: 5284Look at the line hundreds = n // 100 % 10. Python reads // and % from left to right, because they have the same rank. So it first computes 4825 // 100, which is 48, and then 48 % 10, which is 8. Each digit is found by dropping the digits to its right and then taking the last digit with %.
This program only works for four-digit numbers. Once you learn loops, you can write a version that works for any length. The idea is the same: take the last digit with % 10, then drop it with // 10.
Integers do not overflow in Python
In many languages, a whole number has a fixed size, such as 32 bits. When a result is too big for those bits, the value wraps around to the other end of the range. This is called overflow. Python integers do not work that way. An int grows to hold any result, so this program prints the true answer:
The output is:
2**31 - 1: 2147483647
biggest_32 + 1: 2147483648
2**100: 1267650600228229401496703205376The value 2**31 - 1 is the largest number that fits in a signed 32-bit integer. The number 2**100 has 31 digits, and Python prints all of them.
Two things still matter. The first is memory. A very large int takes more memory than a small one, and a loop that multiplies numbers again and again can use a lot of it. The second is that some data must have a fixed size. A file format, a network protocol or a database column may store a value in 32 bits, and the program must keep the value inside that range. The standard library module ctypes gives you fixed-size integer types for that purpose. Its c_int32 type keeps only the lowest 32 bits of the value you give it:
The output is:
c_int32 max + 1: -2147483648
exact sum: 4000000000
as c_int32: -294967296The line with c_int32 shows the wrap. Adding 1 to the largest 32-bit value gives the smallest one. The sum of the two prices is 4000000000, which does not fit in 32 bits. The fixed-size type keeps the low 32 bits, and the result is -294967296. Python itself did not fail. The plain int addition gave the exact sum, and the conversion to a fixed size changed it.
A useful rule for Python is this. Use plain int for ordinary calculations. Check the range yourself, or use a fixed-size type, only when a value must fit a fixed format.
Ceiling division without floating point
One useful trick uses // and % together. Suppose you have 10 items and each page holds 4. You need 3 pages, because the last page is only partly full. Plain 10 // 4 gives 2, which is too few. You can add per_page - 1 before dividing:
The output is:
pages needed: 3
pages for 12 items: 3The formula (items + per_page - 1) // per_page rounds up. For 10 items, 10 + 4 - 1 is 13, and 13 // 4 is 3. For 12 items, 12 + 4 - 1 is 15, and 15 // 4 is 3, which is right because 12 items fill exactly 3 pages.
The standard library has math.ceil, which rounds up. It works on a float, so math.ceil(items / per_page) also gives 3 here. The integer formula avoids decimal rounding entirely, which is why it is the one to use for counting groups.
Worked example: splitting a restaurant bill
Here is a realistic calculation, traced step by step. Three friends share a bill. The meals cost 1250 cents and 899 cents, and tax is 18 percent. Money in code is best stored in cents, as a whole number, so every step below is integer arithmetic.
Step 1. Add the prices. 1250 + 899 is 2149 cents.
Step 2. Work out the tax. The formula is subtotal * 18 // 100. Python evaluates * and // from left to right, so it first computes 2149 * 18, which is 38682. Then 38682 // 100 is 386. The part .82 is cut off, so the tax is 386 cents. The exact tax is 386.82 cents, so the program has chosen to round down. A shop must pick a rounding rule and stick to it.
Step 3. Add the tax. 2149 + 386 is 2535 cents for the total.
Step 4. Split three ways. 2535 // 3 is 845, and 2535 % 3 is 0. Each friend pays 845 cents, which is 8 dollars and 45 cents, and nothing is left over.
Step 5. Change one number. Suppose the bill is 2536 cents. Then 2536 // 3 is still 845, but 2536 % 3 is 1. Each friend pays 845 cents and one cent is left over. The program must decide who pays the extra cent. Real bill-splitting apps handle this with the remainder, and they give the extra cent to one person.
Now see what happens if the order of the tax formula changes. Write the tax as subtotal * (18 // 100). The brackets force 18 // 100 first. Both numbers are integers, so 18 // 100 is 0, and the tax becomes 2149 * 0, which is 0. The meal has become free. This is the same trap as the average problem, and it is the most common arithmetic error in price code. Multiply first, and divide last, whenever you work with whole numbers.
The whole calculation is in one program:
The output is:
subtotal: 2149
tax: 386
total: 2535
each share: 845
left over: 0
bill 2536, each share: 845
bill 2536, left over: 1
wrong tax: 0The example shows the three habits that keep integer arithmetic correct. Store money in the smallest unit. Multiply before you divide. Use the remainder for anything that must add up exactly.
Operator precedence: who goes first
Operators do not run strictly left to right. Each operator has a precedence, which is its rank. Higher-ranked operators are evaluated first. From highest to lowest, the rank for the operators in this lesson is:
- Brackets,
( ). - The power operator
**. - Unary minus, the minus sign in front of one value, as in
-x. - Multiplication
*, true division/, floor division//and the remainder%. These four have the same rank. - Addition
+and subtraction-. These two have the same rank.
Operators on the same rank run from left to right. This is called left-to-right associativity. The power operator is the exception. It runs from right to left, so 2 ** 3 ** 2 means 2 ** (3 ** 2). Brackets always win, so you can use them to force any order you want.
Predict each line of this program before you run it:
The output is:
14
20
10
2
3
512
-4
4Here is the step-by-step reasoning for the trickiest lines.
20 // 4 * 2 has two operators on the same rank, so it runs left to right. First 20 // 4 gives 5, then 5 * 2 gives 10. If you had run the multiplication first, you would have 20 // 8, which gives 2. The left-to-right rule matters.
10 - 4 - 3 is the same case with subtraction. It is (10 - 4) - 3, which is 6 - 3, which is 3. It is not 10 - (4 - 3), which would be 9.
2 ** 3 ** 2 is 512, because the power operator goes from right to left. 3 ** 2 is 9 and 2 ** 9 is 512.
-2 ** 2 is -4, because ** ranks above unary minus. The line means -(2 ** 2). If you want the square of -2, write (-2) ** 2, which is 4.
When you write a long expression in real code, add brackets for clarity even if they are not needed. Brackets cost nothing at run time and make the next reader's job easier. A safe habit is to bracket every division inside a bigger calculation.
Floats are close approximations
A float stores a number in binary, the base-2 system. Some decimal fractions, such as 0.1, have no exact binary form. The stored value is the closest binary number that fits, which is very close but not exact. The result is that simple decimal sums can be slightly off.
The output is:
0.30000000000000004
False
True
True
0.1000000000000000055511151231257827021181583404541015625The first line shows the error. The second line shows that == is false, because the two values differ in the last few binary digits. The third line is the manual test. abs gives the size of a number without its sign, and the comparison asks whether the two values are closer than a tiny tolerance. The fourth line uses math.isclose, the standard library function for the same question. It is the better choice in most code. Use one of these patterns whenever you compare two decimal results.
The last line shows the value that is really stored for 0.1. The Decimal type from the standard library shows its exact digits. The digits after 0.1 are not zero, so the stored value is a little larger than 0.1.
Money is a special case. Shops and banks store amounts in whole cents, as an int, and not as a float. A total of 1234 cents is 12 dollars and 34 cents, and you get both with // and %:
The output is:
12 dollars 34 centsExact integer arithmetic gives an exact answer every time. When you need decimal money arithmetic with explicit rounding rules, the decimal module is the standard tool.
Dividing by zero
What happens when the divisor is zero? In Python the answer is the same for int and float. Both raise an exception. An exception is Python's name for a runtime error. If the program does not handle it, Python stops the program and prints a message.
The output is:
before the error
Traceback (most recent call last):
File "/path/to/main.py", line 3, in <module>
print(10 / zero)
~~~^~~~~~
ZeroDivisionError: division by zeroThe path in the File line depends on where you saved the file. Your output shows your own path there.
Read the output carefully, because you will see messages like this often.
The first line, before the error, prints because it comes before the problem. Python runs the program one line at a time, so the output up to the failing line is kept.
The line Traceback (most recent call last): starts the error report. Python lists the calls that led to the error, the oldest first, and the most recent call last. Here the only call is the line print(10 / zero).
The line File "/path/to/main.py", line 3 names the file and the line number where the error happened. This is the line to look at first.
The line with ~~~^~~~~~ is a marker that points at the part of the line that failed. Here it points at the division.
The last line, ZeroDivisionError: division by zero, names the exception type and the reason. The word before the colon is the type, and the words after it explain the problem.
The line print("this line never runs") never prints, because the error stopped the program at line 3.
If you want a decimal result of infinity, you can ask for it on purpose with math.inf. Dividing by zero does not produce it.
Common mistakes and the messages you will see
Most arithmetic mistakes in Python are silent. They produce a wrong number and no error. Some give an error at run time, and a few give a message before the program starts. Learn to read these messages, because they tell you exactly what to fix.
Mistake 1: int quietly removes the decimal part
The output is:
3
-3The function int does not raise an error for a decimal value. It cuts the decimal part off toward zero. If you want the value rounded to the nearest whole number, use round, but remember that round sends a half to the nearest even whole number, so round(2.5) is 2 and round(3.5) is 4. If you want rounding down for negative numbers too, use math.floor.
Mistake 2: text is a string, not a number
The output is:
Traceback (most recent call last):
File "/path/to/main.py", line 2, in <module>
print(10 / text_number)
~~~^~~~~~~~~~~~~
TypeError: unsupported operand type(s) for /: 'int' and 'str'The value "2" is in quotes, so it is text, not a number. You cannot divide a number by text. Remove the quotes, or convert the text to a number with int("2"). Converting text is covered in the strings module.
Note that int("3.5") is a different error. It raises ValueError, because the text does not hold a whole number:
The output is:
Traceback (most recent call last):
File "/path/to/main.py", line 1, in <module>
n = int("3.5")
ValueError: invalid literal for int() with base 10: '3.5'Use float("3.5") for text that holds a decimal number.
Mistake 3: an incomplete expression
The output is:
File "/path/to/main.py", line 1
x = 5 +
^
SyntaxError: invalid syntaxPython reads the whole program before it runs it. A + must have a value on both sides. Here the line ends after the +, so Python cannot read it. The caret points at the place where it stopped reading. Add the missing value, or remove the operator.
Mistake 4: + with a number and text
The output is:
Traceback (most recent call last):
File "/path/to/main.py", line 1, in <module>
print(1 + 2 + "3" + 4 + 5)
~~~~~~^~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'Python evaluates 1 + 2 first and gets the number 3. Then 3 + "3" is an error, because Python does not join a number and text with +. The message names the two types, int and str. Convert the number to text first, with str(3), or put the numbers in an f-string, such as f"{1 + 2}3".
Mistake 5: a float where a whole number is needed
The output is:
Traceback (most recent call last):
File "/path/to/main.py", line 2, in <module>
for i in range(groups):
~~~~~^^^^^^^^
TypeError: 'float' object cannot be interpreted as an integerThe function range needs a whole number. The / operator returns a float, even when the result is 3.5. Use // when you want a whole number, as in range(7 // 2).
Reading an exception from start to finish
When your program crashes, do not panic. Python prints the error at the bottom of the message. Here is a method for finding the cause.
- Read the last line. It gives the exception type, for example
ZeroDivisionError, and the reason after the colon. - Read the
Fileline that names your own file. That is the line to inspect. - Look at the variables on that line and ask what value each one had. Add
printlines above it if you need to see the values. - If the error came from a function call, read the lines above the
Fileline too. They show the calls that led to the error, in order.
The last line is the most useful, and the lines above it show the path to it.
A debugging walkthrough
Here is a realistic bug. A student writes a program that should print the average of three test scores, 72, 85 and 90, as a decimal number. The program prints 82 instead of 82.33. Let's work through it.
The sum is 247. Then 247 // 3 gives 82, because 247 divided by 3 is 82.33 with the decimal part removed. The expression was wrong, not the variable. The fix is to use true division:
The output is:
82.33333333333333
82.33The first line prints the full value. The second line uses the format .2f inside the f-string, which means two digits after the point. The arithmetic fix came first, and the display format came second. Keep the two steps separate in your head.
The general method for an arithmetic bug is the same. Write the type of every operand next to it, then ask at each operator whether the result is a whole number or a decimal. The bug is usually at a // where you wanted /, or at a place where a whole number is stored where a decimal was needed.
Variations and edge cases
Interviewers like to test edge cases. Here are the ones you should check every time.
- Zero. Division by zero is an error for both
/and//, and for%. The remainder of zero by any non-zero number is zero, so0 % 5is0. - Negative numbers. Floor division rounds down, so
-7 // 2is-4. The remainder takes the sign of the divisor, so-7 % 2is1. The functionintrounds toward zero instead, soint(-7 / 2)is-3. - Very large inputs. Python does not overflow, but the calculation can be slow or use a lot of memory when the numbers have millions of digits.
- One operand is a decimal. Check where the decimal enters the expression and whether a division happens before or after it.
These cases are easy to check with small programs. Try each one before you trust a formula.
Interview-style patterns
Arithmetic questions appear in interviews as small puzzles. Three patterns come up often.
Digit manipulation. The loop while n > 0: with digit = n % 10 and n = n // 10 visits every digit from the right. You can use it to sum digits, count digits, reverse a number or check a palindrome. The cost is one step per digit, so for a number with d digits the work is proportional to d.
Ceiling and rounding. To round up an integer division for positive values, use (a + b - 1) // b. To round to the nearest integer with halves rounded up, use (a + b // 2) // b for positive values. Both avoid floats, which keeps the answer exact.
Greatest common divisor. Euclid's method finds the largest number that divides two positive integers evenly. It uses the remainder operator. For 84 and 36, you compute 84 % 36, which is 12. Then you replace the pair with 36 and 12. Next is 36 % 12, which is 0. The last non-zero value, 12, is the answer. The standard library has this as math.gcd, which you can use directly.
The output is:
12Each of these patterns runs in a fixed or small number of steps, so their time cost is easy to state. A digit loop does one step per digit. A ceiling formula does one step, always. Euclid's method takes a number of steps that grows with the number of digits in the inputs, which is very small. A later module explains these costs formally.
A question interviewers ask
A common interview question is this. Reverse the digits of a 32-bit integer, and say what can go wrong.
The usual method takes the last digit with % 10, adds it to the result after multiplying the result by 10, and removes the digit with // 10. Take 123. The steps are: last digit 3, result 3. Then last digit 2, result 32. Then last digit 1, result 321. Each step is one line of arithmetic, and the loop runs once per digit.
The trap is the size of the answer. The input 1534236469 reverses to 9646324351, which is larger than the largest 32-bit signed value, 2147483647. Python will happily store the bigger number, so the check must be done in the program. A good answer computes the reversed number, then checks whether it fits in 32 bits, and returns 0 when it does not.
Negative input needs care in Python. -123 % 10 is 7, not -3, and -123 // 10 is -13, not -12. The sign rule of Python makes the digit loop wrong for negative numbers unless you work with the absolute value first. The program below does that:
The output is:
321
-321
0The function abs gives the size of a number without its sign. The variable sign remembers the original sign, and the result gets it back at the end. The last check returns 0 for the input 1534236469, because the reversed value does not fit in 32 bits.
When you answer this in an interview, name three things: the digit loop, the range check, and the sign rule. That shows you understand the operators, not just the puzzle.
Practice
1. (Easy) What do print(17 / 5) and print(17 // 5) print? What does print(17 % 5) print?
Show the answer
17 / 5 prints 3.4, because true division keeps the decimal part. 17 // 5 prints 3, because floor division drops it. 17 % 5 prints 2, because 5 fits into 17 three times and 2 is left over.
2. (Easy) What does print(9 / 2.0) print, and why is it different from 9 // 2?
Show the answer
It prints 4.5. Division with / always gives a decimal result. 9 // 2 prints 4, because floor division drops the part after the point.
3. (Easy) What is -9 % 4 in Python?
Show the answer
It is 3. The remainder takes the sign of the divisor, which is positive here. Floor division gives -9 // 4 equal to -3, and (-3) * 4 + 3 equals -9, so the remainder is 3.
4. (Easy) Given cents = 1234, print the dollars and the cents with one line each.
Show the answer
cents = 1234
print(cents // 100)
print(cents % 100)The output is 12 and then 34.
5. (Medium) Write one expression, using only % and ==, that is true when n is even for every integer n, including negatives.
Show the answer
n % 2 == 0. An even number leaves no remainder for any sign, so the remainder is 0.
6. (Medium) Predict the output of print(2 + 3 * 4 - 6 / 3).
Show the answer
It prints 12.0. The multiplication and division run first: 3 * 4 is 12 and 6 / 3 is 2.0. Then the addition and subtraction run from left to right: 2 + 12 is 14, and 14 - 2.0 is 12.0. The / makes the result a float, so the answer has a decimal point.
7. (Medium) Predict the output of print(1 + 2 + "3" + 4 + 5).
Show the answer
It is an error, not a number. 1 + 2 is 3, and then 3 + "3" raises a TypeError, because Python does not add a number and text. Fix it with print(1 + 2 + int("3") + 4 + 5), which prints 15, or with print(f"{1 + 2}3"), which prints 33.
8. (Medium) Write the average of the integers 7, 8 and 8 as a decimal with full precision. What does it print?
Show the answer
average = (7 + 8 + 8) / 3
print(average)It prints 7.666666666666667. Use / for the decimal result. With // the answer would be 7.
9. (Medium) Write an expression for the number of boxes needed to hold items objects if each box holds 25. Use only integer operators.
Show the answer
(items + 24) // 25. Adding 24 before floor division rounds up. For 101 items the answer is 125 // 25, which is 5, and for 100 items it is 124 // 25, which is 4.
10. (Hard) Predict the output of this code, then explain it.
import ctypes
big = 2000000000
total = big + big
fixed = ctypes.c_int32(big + big).value
print(total, fixed)Show the answer
It prints 4000000000 -294967296. The plain int addition is exact, because Python integers grow as needed. The ctypes.c_int32 conversion keeps only the lowest 32 bits of 4000000000. That value is larger than the 32-bit maximum, so the stored result is 4000000000 minus 4294967296, which is -294967296.
11. (Hard) Write a boolean expression that is true when two float values a and b are equal to within one millionth. Explain why a == b is the wrong test.
Show the answer
abs(a - b) < 0.000001, or math.isclose(a, b, abs_tol=0.000001). The test a == b is wrong because binary approximation can make two results that should be equal differ in the last digits, as 0.1 + 0.2 shows. The test asks whether the distance between the values is smaller than the tolerance.
12. (Hard) For positive integers a and b, compute a / b rounded to the nearest integer, with halves rounded up, using only integer operators. Check it with 7 / 2 (answer 4) and 9 / 4 (answer 2).
Show the answer
(a + b // 2) // b. For 7 / 2, b // 2 is 1, so the value is 8 // 2, which is 4. For 9 / 4, b // 2 is 2, so the value is 11 // 4, which is 2. Adding half of b before floor division is the same as adding one half to the real quotient and then rounding down.
What you now know
- An expression is a group of operators and operands that makes one value, and every value has a type.
/always gives afloat.//rounds down to a whole number. Use/for measured values and//for counting groups.%gives the remainder, and its sign follows the divisor, so-7 % 2is1.**runs first, then unary minus, then*,/,//and%, and then+and-. Brackets win over everything.- Python
intvalues do not overflow. Fixed-size types such asctypes.c_int32do. - Dividing by zero raises
ZeroDivisionErrorfor bothintandfloat. - Error messages name the exact problem, and the
Fileline points at the failing line. - Ceiling division, digit extraction and Euclid's method are the arithmetic patterns that interviews use.