Scoreboard Arithmetic in a Step-Challenge Script
Priya is writing a warm-up script for a school step challenge. Step counts arrive from a web form, so she keeps them as text and then applies a bonus multiplier. Her file contains:
steps = "1200" bonus = 3 total = steps * bonus print(total) average = 1200 + 800 / 2 print(average) print(7 // 2, 7 % 2, 2 ** 3)
The program prints 120012001200 instead of the 3600 she expected, and the average appears with a decimal point. She also wants the last line to read 3 1 8 but is unsure whether //, %, and ** bind more tightly than the comma inside print. Her teacher asks her to justify each result instead of patching the output. The value stored in steps must stay exactly as received, because the original text is displayed elsewhere in the report and must not be reformatted.
1. State the exact output of all three `print` calls and explain, for each line, which Python rule produces it.
Read the worked answer
Line 1 - 120012001200. steps is a str and bonus is an int. For a string on the left, * means repetition, not multiplication: "1200" * 3 builds "120012001200". print shows the characters without quotes, which is why the result looks like a huge number.
Line 2 - 1600.0. / is true division in Python 3 and always returns a float, so 800 / 2 is 400.0, not 400. Adding an int (1200) to a float promotes the result to float, giving 1600.0. The decimal point is not an error; it is the defined return type of /.
Line 3 - 3 1 8. 7 // 2 is floor division (3), 7 % 2 is the remainder (1), and 2 ** 3 is exponentiation (8). There is no precedence contest with the commas: each comma separates a separate argument to print, and each argument is evaluated independently before printing. The single spaces come from print's default sep, not from the operators.
2. Give the minimal change that makes `total` equal the integer 3600 while leaving `steps` untouched, and explain why Python will not make that conversion on its own.
Read the worked answer
Minimal change, on the total line only:
total = int(steps) * bonus
int("1200") parses the text into the integer 1200, and 1200 * 3 is 3600. steps still holds "1200", so the report text is unaffected.
Python never silently converts a string to a number. The operations + and * already have string meanings (concatenation and repetition), so the language cannot know whether "1200" * 3 was intended as arithmetic or as repetition. Type conversion is always explicit.
Note the alternatives: float(steps) * bonus yields 3600.0; it compares equal to 3600 (3600.0 == 3600 is True) but has a different type and prints with .0. Also, int("1200.0") would raise ValueError, so int is only safe if the incoming text has no decimal point.
3. Predict the output of `print(-7 // 2, -7 % 2)` and justify it, including why many beginners expect a different answer.
Read the worked answer
Output: -4 1.
Floor division rounds toward negative infinity, not toward zero: the true quotient -3.5 floors to -4. Many people mentally truncate instead (as C does) and expect -3.
The remainder must satisfy the identity a == (a // b) * b + a % b. Substituting gives -7 == (-4) * 2 + r, so -8 + r = -7 and r == 1. A useful shortcut is that % in Python takes the sign of the divisor, so a positive divisor produces a non-negative remainder even when the dividend is negative.
This matters when checking parity: -7 % 2 == 1 is truthy, and -7 // 2 == -4 is not the same as int(-7 / 2), which gives -3.