Recursive C Functions 197
difference of time before and after calculating Fibonacci numbers. The basic structure of
measuring a function’s execution time is
1. get the current time, call it t1;
2. call the function;
3. get the current time, call it t2.
The execution time of this function is t2 − t1. This method of measuring execution time
has limitations. The time t1 and t2 has finite precision. If this function’s execution time
is too short, t2 − t1 will be too small (possibly zero). To obtain acceptable accuracy, the
execution time needs to be much longer than the precision. For gettimeofday, the precision
is microseconds; thus, the execution time should be much longer than one microsecond. This
is the reason why the program calls the functions calculating Fibonacci numbers multiple
times between calling gettimeofday. The values may be slightly different when the program
is run multiple times because your computer also runs many other programs. This is the
last few lines of the program’s output:
fib (16) = 987 , time = 2.161532
fib2 (16) = 987 , time = 0.004730
ratio = 456.9 83490
fib (17) = 1597 , time = 3.500462
fib2 (17) = 1597 , time = 0.0050 9 3
ratio = 687.3 08472
fib (18) = 2584 , time = 5.678572
fib2 (18) = 2584 , time = 0.0054 7 4
ratio = 1037 .371704
fib (19) = 4181 , time = 9.399386
fib2 (19) = 4181 , time = 0.0056 7 7
ratio = 1655 .696045
fib (20) = 6765 , time = 15.53051 3
fib2 (20) = 6765 , time = 0.0078 6 2
ratio = 1975 .389648
As you can see, the ratios of the execution time grow from 457 to 1975.
(c) (d)
f(5) = f(4) + f(3)
f(3) + f(2)
f(2) + f(1)
f(2) + f(1)
1
1 1
1 1
f(5) = f(4) + f(3)
f(3) + f(2) f(2) + f(1)
f(2) + f(1)
1
1 1
f(5) = f(4) + f(3)
f(3) + f(2) f(2) + f(1)
f(5) = f(4) + f(3)
FIGURE 13.3: Computing f(5) requires calling f (4) and f (3). Computing f(4) requires
calling f(3) and f (2).
Why is there such a large difference in the execution time? Fig. 13.3 illustrates the
sequence of computation. For the first function, to compute f (5), it is necessary to compute
f(4) and f (3). To compute f(4), it is necessary to compute f(3) and f (2). Fig. 13.4 redraws
Fig. 13.3. This looks like a “tree”. You need to use some imagination because the tree’s
“root” is at the top and the branches go downwards. Computing each value requires the
sum of two values, until reaching the bottom, called leaves. The leaves are the base cases,
where the recursion meets the terminating conditions, namely f (1) or f(2).
Let’s do a little more mathematics here to figure out some properties of this tree. By
definition,