There are several ways you can approach this. While recursive functions can provide elegant solutions for some problem where a non-recursive approach is difficult, recursion in general should not be your first choice. Why? Each recursive call is a separate function call that requires the setup and resources of a complete function stack. If you recurse too many times, you will actually learn about StackOverflow...
That said, learning recursive functions are a necessary part of learning to program. Here the number of recursive calls is limited to n
so you are safe. Every recursive function has two things:
- an exit condition that stops the recursion; and
- a recursive call.
You want to preserve a sum over your recursive calls. A static
variable initialized on its first declaration will do. So in this case, you can do something like:
double sum (int n)
{
static double val = 0.;
if (n) {
val += 1. / n;
sum (n - 1);
}
return val;
}
The scheme above is relatively simple. You use a check for a positive value for n
as your exit condition, and each time you make a recursive call you reduce the value of n
by 1. If you want to see how your recursion is progressing, you can add debug output between the update of val
and the recursive call to sum (n - 1)
such as:
std::cout << "n:" << n << " frac: 1/" << n << " val: " << val << '\n';
A short example that takes the first argument to the program as n
could be:
#include <iostream>
#include <string>
double sum (int n)
{
static double val = 0.;
if (n) {
val += 1. / n;
sum (n - 1);
}
return val;
}
int main (int argc, char **argv) {
/* initialize with 1st argument to program (default: 2) */
std::string s { argc > 1 ? argv[1] : "2" };
int n;
try { /* stoi must have exception handler */
n = stoi (s); /* attempt conversion */
std::cout << sum (n) << '\n'; /* output result */
}
catch (const std::exception & e) { /* catch exception return error */
return 1;
}
}
Example Use/Output
The resulting values for n
from 0
to 20
would be:
$ for i in {0..20}; do printf "%2d " $i; ./bin/frac_sum_recurse $i; done
0 0
1 1
2 1.5
3 1.83333
4 2.08333
5 2.28333
6 2.45
7 2.59286
8 2.71786
9 2.82897
10 2.92897
11 3.01988
12 3.10321
13 3.18013
14 3.25156
15 3.31823
16 3.38073
17 3.43955
18 3.49511
19 3.54774
20 3.59774
While you are building good habits learning C++, have a look at: Why is “using namespace std;” considered bad practice?. Here it would save no more than three std::
.
Look things over and let me know if you have further questions.