Trace Tables and Debugging
Working through an algorithm by hand with a trace table, saying what it is for, and finding and fixing the errors a question hides in it. These are the marks other candidates lose.
Trace tables
A trace table records the value of every variable after each step of an algorithm. It is how you find out what code really does, as opposed to what you think it does, and it is a standard question on every GCSE paper.
The method never changes:
- One column for each variable, plus one for the output
- One row for each pass of a loop, or each time a variable changes, working strictly in program order
- Write the value a variable has after the pass, and put a dash in a box only if the variable does not have a value yet
Worked example 1: a loop
total = 0
for i in range(1, 5):
total = total + i * 2
print(i, total)i | total | Output |
|---|---|---|
| - | 0 | - |
| 1 | 2 | 1 2 |
| 2 | 6 | 2 6 |
| 3 | 12 | 3 12 |
| 4 | 20 | 4 20 |
The loop runs for 1, 2, 3 and 4. It does not run for 5, because range stops before its second value.
Worked example 2: a while loop with MOD and DIV
number = 4721
total = 0
while number > 0:
digit = number % 10
total = total + digit
number = number // 10
print(digit, total, number)
print("Digit sum:", total)number | digit | total | Output |
|---|---|---|---|
| 4721 | - | 0 | - |
| 472 | 1 | 1 | 1 1 472 |
| 47 | 2 | 3 | 2 3 47 |
| 4 | 7 | 10 | 7 10 4 |
| 0 | 4 | 14 | 4 14 0 |
| - | - | - | Digit sum: 14 |
number % 10 peels off the last digit and number // 10 throws it away. When number reaches 0 the test number > 0 is false and the loop ends. Notice that the last row has number equal to 0 and yet the digit of that row is 4, because the loop body ran once more with number still 4 before it was cut to 0.
Step 1 of 6 Before the loop, total is 0 and number is 4721.
Finding the purpose
Often the question does not ask for the table. It asks what the algorithm does. Trace it with small numbers and then describe the result, not the steps.
a = 48
b = 18
while b != 0:
temp = b
b = a % b
a = temp
print(a)a | b | temp |
|---|---|---|
| 48 | 18 | - |
| 18 | 12 | 18 |
| 12 | 6 | 12 |
| 6 | 0 | 6 |
It prints 6, which is the highest number that divides both 48 and 18. The algorithm finds the highest common factor of two numbers. It is more than 2,000 years old and is named after Euclid.
"It sets temp to b, then b to a MOD b" is a description of the lines and earns nothing. "It outputs the highest common factor of the two numbers" is a description of the purpose and earns the mark. Trace with small values to see the answer, then state it in one sentence.
- Run the program by hand, one line at a time. Line 3 is the one that repeats.
- Follow four rules: one line at a time, one column per variable, a new row for each change, and check the last row.
- Each time the loop runs, i goes up by one and total grows: 0, 1, 3, 6.
- The output is written when print runs. Here it is 6.
Finding and fixing errors
The exam gives you an algorithm that does not work, asks you to find the error, and asks for the corrected line. Nearly all of them are one of these:
| Fault | What it does | How you spot it |
|---|---|---|
| Off by one | Loop runs one time too many or too few | Compare the first and last values with the specification |
| Wrong comparison | > for >=, and for or | Test at the boundary |
| Variable started wrong | A maximum that begins at 0 | Test with all negative numbers |
| Variable reset in the wrong place | A total set to 0 inside the loop | Trace two passes of the loop |
| Return in the loop | A function stops after one item | Check indentation of return |
| Wrong type | Adding text to a number | Read the error message |
Six faults, each one running
An off by one error. The aim is 1 to 5:
for i in range(1, 5):
print(i, end=" ") # 1 2 3 4: the 5 is missing
print()
for i in range(1, 6):
print(i, end=" ") # 1 2 3 4 5
print()A total reset in the wrong place. The aim is the average of three marks:
marks = [50, 60, 70]
total = 0
for mark in marks:
total = 0 # fault: this wipes out the running total
total = total + mark
print(total / len(marks)) # 23.333333333333332
total = 0
for mark in marks:
total = total + mark
print(total / len(marks)) # 60.0A return inside the loop. The aim is to add every number:
def total_of(numbers):
total = 0
for n in numbers:
total = total + n
return total # fault: leaves the function on the first pass
return total
print(total_of([1, 2, 3])) # 1The return must line up with the for, so it runs once the loop has finished. Move it left by one level and the answer is 6.
A starting value that is wrong. The aim is the largest number:
numbers = [-4, -9, -2, -7]
largest = 0
for n in numbers:
if n > largest:
largest = n
print(largest) # 0, which is not even in the list
largest = numbers[0]
for n in numbers:
if n > largest:
largest = n
print(largest) # -2A type error. Text and numbers cannot be joined with a plus:
# raises: TypeError
score = 7
print("Score: " + score)The fix is print("Score: " + str(score)), or print("Score:", score).
An assignment where a comparison was meant:
# raises: SyntaxError
score = 7
if score = 7:
print("Seven")Python catches this one before it runs and says Maybe you meant '==' instead of '='. A logic error you have to find yourself, and a syntax error the computer finds for you.
A question that says "identify the error and correct it" has a mark for naming the line, a mark for the correct replacement, and often a mark for the effect the error has. State all three.
- Syntax error: the code breaks the rules of the language, so it will not run at all.
- Runtime error: the program starts, then crashes when it meets something it cannot do.
- Logic error: it runs without complaint but gives the wrong answer, so only testing finds it.
Debugging tools and techniques
Debugging is finding out why a program is wrong. The tools and habits below are in the specification, and they work in this order.
Read the error message
The last line names the error and the line above it gives the position. Python's messages are written to be read.
Print to see inside
The most common technique, and the one professionals still use first: print a variable at the point you are unsure about.
def average(marks):
total = 0
for mark in marks:
total = total + mark
print("added", mark, "total is now", total)
return total / len(marks)
print(average([50, 60, 70]))Test small, test early
Run each subprogram on its own with values you can work out in your head, before you build the next one on top of it.
Check with assert
assert states something that must be true. If it is not, the program stops at that exact line and says so, which is far better than a wrong answer appearing three screens later.
def grade_for(mark):
if mark >= 70:
return "Distinction"
elif mark >= 50:
return "Merit"
return "Fail"
assert grade_for(70) == "Distinction"
assert grade_for(69) == "Merit"
assert grade_for(50) == "Merit"
assert grade_for(49) == "Fail"
print("All four tests passed")What an IDE gives you
An integrated development environment puts the tools in one program. The exam names these:
| Tool | What it does for you |
|---|---|
| Editor | Writes the code, with colour and automatic indentation |
| Error diagnostics | Highlights faults and reports their line |
| Run time environment | Runs the program so you can see the output |
| Translator | Turns the code into machine code, reporting syntax errors as it does |
| Debugger | Lets you run one line at a time |
| Breakpoint | Pauses the program at a chosen line |
| Variable watch | Shows the value of variables while it is paused |
Pause the program at the line you do not trust, step forward one line at a time, and watch each variable change. It does by machine what you do on paper in a trace table.
- Editor: colours the code and numbers the lines.
- Auto-complete: suggests names as you type, which saves typing and typos.
- Error check: underlines mistakes in red before you run the program.
- Debugger: breakpoints, stepping and a watch window to see what the variables hold.
- Console: where output and error messages appear.
- Project files: everything in one place.
Key terms you must be able to define
- Trace table
- A table that records the value of each variable after every step of an algorithm.
- Dry run
- Working through an algorithm by hand, without running it, to check what it will do.
- Debugging
- Finding and fixing faults in a program.
- Syntax error
- A mistake in the rules of the language, which stops the program from running.
- Logic error
- A mistake that lets the program run but produces the wrong result.
- Breakpoint
- A point in a program where a debugger pauses it, so the programmer can inspect it.
- Variable watch
- A debugging tool that shows the current value of chosen variables as the program runs.
- Off by one error
- A fault where a loop or an index is one too many or one too few.
- IDE
- Integrated development environment: a program that combines an editor, translator and debugging tools.
Flashcards
Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.
Reach the top grade on this topic
Tracing questions are the most reliably gained marks on the paper, and the most reliably thrown away.
- Give every variable its own column, and write each row in the order the program runs
- Trace with the exact numbers you were given, never with ones you invent
- State the purpose of an algorithm as a result: highest common factor, total, count, maximum
- When asked to correct an error, name the line, write the fixed line, and say what it now does
- Name the IDE tool and what it does: a breakpoint pauses, a watch shows a value
Mistakes that cost marks here
- Skipping the final pass of a loop, or doing one pass too many.
- Describing what each line does instead of what the algorithm achieves.
- Writing the value before a line runs in a trace table instead of after it.
- Correcting a symptom, such as adding one to an answer, instead of the fault that caused it.
- Confusing a syntax error, which stops the program, with a logic error, which does not.
In 1969 the Apollo 11 guidance computer raised overload alarms on the way down to the Moon. Software written by Margaret Hamilton's team had been designed to drop the unimportant jobs and keep the vital ones running, so the landing went ahead. She is credited with coining the phrase software engineering.
Knowledge check
x = 1, then y = 10, then while y > 4: with x = x * 2 and y = y - 3 inside. What is x at the end?number % 10 give for 4721?return inside the loop. What does it return for [1, 2, 3]?largest = 0. For which list does it give the wrong answer?a MOD b until b is 0?Exam-style questions
Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.
x = 1
y = 10
while y > 4:
x = x * 2
y = y - 3
print(x)- Lx is 2 and y is 7 after the first pass
- Lx is 4 and y is 4 after the second pass, and the loop then stops because 4 is not greater than 4
- LThe value output is 4
After the first pass x is 2 and y is 7. After the second pass x is 4 and y is 4. The condition y > 4 is now false, because 4 is not greater than 4, so the loop stops without a third pass, and the value output is 4.
a = 48
b = 18
while b != 0:
temp = b
b = a % b
a = temp
print(a)- LIt finds the highest common factor of the two numbers
- LOf a and b, or 48 and 18
- LThe value output is 6
The algorithm finds the highest common factor of the two numbers, which is the largest whole number that divides exactly into both. For 48 and 18 the values of b are 18, 12, 6 and 0, and the algorithm outputs 6.
numbers = [-4, -9, -2, -7]
largest = 0
for n in numbers:
if n > largest:
largest = n
print(largest)- Llargest is set to 0 before the loop
- LAll the numbers in the list are negative, so none is greater than 0
- LThe program outputs 0, which is not in the list
- LThe corrected line is largest = numbers[0]
The error is that largest starts as 0. Every number in the list is negative, so none of them is greater than 0, the test never succeeds, and the program outputs 0, which is not in the list at all. The line should be largest = numbers[0], so the comparison starts from a value that really is in the list. The correct output is -2.
score = 7
if score = 7:
print("Seven")- LIt is a syntax error
- LThe corrected line is if score == 7:
This is a syntax error. A single equals sign assigns a value, and a comparison needs two, so the line should read if score == 7: and the program can then run.
- LA breakpoint pauses the program at a chosen line
- LSo the programmer can inspect the state, or step through one line at a time
- LError diagnostics highlight the line with a fault and describe the problem
- LSo the programmer is taken straight to the fault without searching
A breakpoint pauses the program at a line chosen by the programmer, so the values of the variables can be inspected, and the program can then be stepped through one line at a time to see exactly where the values stop being what was expected. Error diagnostics highlight the line containing a fault and describe the problem, so the programmer is taken straight to where it is rather than having to search the whole program for it.