What the code is supposed to do
The function computeSum takes a number n and should return the sum of the whole numbers from 0 up to n - 1, that is, 0 + 1 + 2 + ... + (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 instead:
function computeSum(n: number): number {
let sum: number = 0;
for (let i = 0; i < n; i++) {
sum += n;
}
return sum;
}
// Do not change this code:
console.log(computeSum(4));
Your job is to find the mistake and fix it.
What goes wrong
The number 16 is a clue. It equals 4 + 4 + 4 + 4, which is four copies of the argument. Look at what the loop adds on each pass: sum += n. The variable n is the function's argument, and it is 4 on every pass. It never changes. The loop does run four times, with i equal to 0, 1, 2 and 3, but the body ignores i.
Here is the trace:
- Start:
sumis 0. - Pass with
i = 0:sumbecomes 0 + 4 = 4. - Pass with
i = 1:sumbecomes 4 + 4 = 8. - Pass with
i = 2:sumbecomes 8 + 4 = 12. - Pass with
i = 3:sumbecomes 12 + 4 = 16.
In general the function adds n to the total n times, so it returns n * n. For 4 that is 16, and for 5 it would be 25. The function is not summing a series of different numbers. It is multiplying the argument by itself the slow way.
This kind of bug happens because both n and i are valid names holding numbers, so the code compiles and runs. TypeScript cannot know which one you meant, because both are of type number. The result is simply a wrong value.
Fixing it step by step
- Find the line that updates the total. It is the one inside the loop:
sum += n. - Decide what should be added. The numbers to add are 0, 1, 2, ...,
n - 1, and these are exactly the values the loop counteritakes on. The thing that changes from one pass to the next is the thing to add. - Replace
nwithi. The line becomessum += i. - Leave everything else. The loop bounds, the starting value 0 of
sum, thereturnand the final call are already right.
The fixed code in TypeScript
function computeSum(n: number): number {
let sum: number = 0;
for (let i = 0; i < n; i++) {
sum += i;
}
return sum;
}
console.log(computeSum(4));
Now the trace for computeSum(4) is 0, then 0 + 0 = 0, then 0 + 1 = 1, then 1 + 2 = 3, then 3 + 3 = 6, and the program prints:
6
Some TypeScript details in this code:
- The return type is
number. The function hands the total back to the caller, and the call at the bottom passes it toconsole.log. The function itself prints nothing. - The type of
iis inferred. There is no annotation oniin this loop, but TypeScript infersnumberfrom the starting value 0. Annotations are erased when the code is compiled to JavaScript. - The upper limit is exclusive. The condition
i < nmeans the last value added isn - 1. That matches the task, but the sum "throughn" would needi <= n. - Numbers are doubles. A
numberkeeps whole values exact up to2^53, so sums of ordinary sizes never overflow or wrap around.
Common mistakes
- Changing the loop instead of the body. The loop already counts correctly. Altering its bounds without fixing
sum += nstill adds copies ofn. - Starting
sumat something other than 0. The total must start at 0 so that nothing extra gets added. - Moving the return into the loop. A
return sum;inside the loop ends the function after the first pass and returns 0. - Changing the call at the bottom. The line
console.log(computeSum(4));must stay as it is. - Using the wrong limit. With
i <= nthe function addsnas well, andcomputeSum(4)returns 10 instead of 6.
Testing
computeSum(4)returns6.computeSum(0)returns0, since the loop does not run.computeSum(1)returns0, because only 0 is added.computeSum(10)returns45.
With the buggy version, computeSum(5) returns 25 and computeSum(4) returns 16, which shows the pattern of n * n.