What the code is supposed to do
The function computeSum takes an integer n and returns the sum of the whole numbers from 0 up to n - 1. For computeSum(4) that is 0 + 1 + 2 + 3 = 6, and the program should print 6. The code you start with prints 16:
func computeSum(n int) int {
sum := 0
for i := 0; i < n; i++ {
sum += n
}
return sum
}
What goes wrong
The loop is set up correctly. Its counter i takes the values 0, 1, 2 and 3, and it stops before reaching n. The mistake is in what the loop adds. The line sum += n adds the parameter n, which is 4 on every pass, instead of the counter i, which changes.
The hint in the lesson, "16 is 4 + 4 + 4 + 4", describes it exactly. The loop makes four passes and adds 4 each time:
i = 0: sum = 0 + 4 = 4
i = 1: sum = 4 + 4 = 8
i = 2: sum = 8 + 4 = 12
i = 3: sum = 12 + 4 = 16
In general, the loop runs n times and adds n each time, so the result is always n * n. That is why 4 gives 16, 5 would give 25, and so on. The counter exists but never takes part in the sum.
Fixing it step by step
- Find the line that updates the total. It is the only line in the loop body:
sum += n. - Ask which value should go in. The task adds 0, then 1, then 2, up to
n - 1. Those are exactly the values the loop counter takes. - Replace
nwithi. The line becomessum += i. - Leave everything else. The start value 0, the condition
i < nand thereturnare already right.
The fixed code in Go
func computeSum(n int) int {
sum := 0
for i := 0; i < n; i++ {
sum += i
}
return sum
}
func mainFunction() {
fmt.Println(computeSum(4))
}
/* Explanation:
The problem was on line 4 because we added n to sum, and so for computeSum(4) for example:
0. sum is initially 0. We enter the for loop:
1. When i is 0 => sum += 4 => sum is now 4
2. When i is 1 => sum += 4 => sum is now 4 + 4 = 8
3. When i is 2 => sum += 4 => sum is now 8 + 4 = 12
4. When i is 3 => sum += 4 => sum is now 12 + 4 = 16
In general, that code would add n to sum for n times, so sum would be n * n when the loop ends.
On line 4, we should add i to sum instead (sum += i).
And so for computeSum(4) for example:
0. sum is initially 0. We enter the for loop:
1. When i is 0 => sum += 0 => sum is now 0
2. When i is 1 => sum += 1 => sum is now 0 + 1 = 1
3. When i is 2 => sum += 2 => sum is now 0 + 1 + 2 = 3
4. When i is 3 => sum += 3 => sum is now 0 + 1 + 2 + 3 = 6
*/
With the fix, the program prints:
6
Go details worth knowing:
- The comment block. Text between
/*and*/is a comment. The compiler ignores it. - The compiler can't catch this bug. Adding
ninstead ofiis valid Go, so the program compiles and runs and only the output is wrong. intarithmetic. Sums stay exact as long as they fit in 64 bits, which is far beyond anything this lesson uses.
How to find a bug like this
When the output is wrong, compare it with the expected value and look for a pattern. Here, 16 is 4 * 4, which suggests that the same number is added several times. That points at the line that updates the total, and then at the question of whether the added value changes from pass to pass. A short trace on paper, like the table above, confirms the suspicion in a minute.
Common mistakes
- Changing the loop bound instead of the body. Using
i <= nwould add one more pass. With the fix applied, that gives 0 + 1 + 2 + 3 + 4 = 10, not 6. The task excludesnitself. - Starting
iat 1. That gives the right answer here, because adding 0 changes nothing, but the loop then starts one pass later than the task describes. - Using a formula without testing it. The sum of the numbers from 0 to
n - 1isn * (n - 1) / 2, which gives 6 for 4. A formula is fine, but this lesson fixes the loop. - Resetting
suminside the loop. Movingsum := 0into the loop body would restart the total on every pass, andreturn sumwould not even compile becausesumwould be out of scope.
Checking your fix
Run the code in the editor above. It should print 6. Other values to try: computeSum(1) is 0, computeSum(0) is 0 because the loop never runs, and computeSum(5) is 10.