The overall approach to the recursion is completely wrong.
Mutating global state is a bad idea even in the best conditions. It's especially important to avoid that when using recursion, because it makes it much harder to reason about the code correctly.
Functions should normally signal the result of the calculation by return
ing it. This is especially important for recursive functions. That's what return
is for.
The point of using recursion here (admittedly a trivial example) is that it already decomposes and simplifies the problem at each step: we use the recursion to find the sum of all the other cubes, and then add the cube for the current digit. Therefore, the correct recursive code should not have a while
loop.
Please make sure you have a solid understanding of how calling a function works. Writing int sumCube(int) {
means that the function accepts a parameter, but can't use it because there is no name for it. We should write a name: int sumCube(int num) {
. Then, only inside the function, num
is a name for whatever was passed in as an argument. This does not have to be another variable named num
; it does not have to be a variable at all. We do not pass variables to functions. We pass values to functions.
You know, exactly like how when you write pow(sumCube(num), 3)
, the 3
didn't have to be a variable at all, and didn't have to have a name dictated by the pow
function. Exactly like how when you use the pow
function, it return
s a value that you can use on the right-hand side of +
, and doesn't change any global variable.
With that background in mind, we can approach the problem fresh. Think about it this way: imagine that you had someone else's function, sumCube2
, which solves the same problem in some other way. We want to use it to help solve the problem. What is our general approach?
We want to give sumCube2
a simpler problem than the one that we got (or else we could have just used it directly). We have a decomposition step already: we use division and modulo to extract the last digit.
We want to combine the result from calling sumCube2
, with some local calculation. It's easy to see how to do this: we cube the last digit, and add the result from the function call to that cubed value. Then we can return
that result.
We need to guard against the problem of running out of room for simplification. This is simple: if we're given 0
, then we know the result is 0
, and we don't have to do any more work. (There are other ways to implement this step, but why make it any harder?)
So: We need a function that accepts a parameter named num
:
int sumCube(int num) {
int last, rest;
We will first check our special case:
if (!num) return 0;
Otherwise, we extract the last digit, and separate the rest of the number:
last = num % 10;
rest = num / 10;
We compute and return
the result, by making use of the sumCube2
result:
return sumCube2(rest) + pow(last, 3);
}
Notice that we don't need to modify any global variables, use a while
loop, or anything like that.
We can condense the code a little bit, since we don't really need names for those intermediate calculation results (that was just to be able to talk about the logic one step at a time):
int sumCube(int num) {
if (!num) return 0;
return sumCube2(num / 10) + pow(num % 10, 3);
}
(Or we could use a ?:
conditional expression, or we could use multiplication explicitly instead of calling pow
, you get the idea.)
Now, how do we make this use recursion, and not have to depend on the mythical sumCube2
that we didn't write?
Simple: sumCube
is a function that is intended to do exactly what sumCube2
was going to do. So we just call it instead - i.e., make the recursive call there.
int sumCube(int num) {
if (!num) return 0;
return sumCube(num / 10) + pow(num % 10, 3);
}
It works because every call to the function gets its own parameters and its own local variables, and return
s back to where it was called from - exactly like calling any other function. Because we only expect the recursive call to do part of the work, and because we only recurse when there is a valid "part of" the work to do recursively, we avoid infinite recursion.
Notice that I do not have any cout
logic in this code. That is because the purpose of sumCube
is to compute the sum of the cubes. Displaying that result is a completely separate and unrelated task. It is the responsibility of main
:
int main()
{
cout << sumCube(51) << endl;
return 0;
}