Test Yourself #3
Question 1:
The call factorial(3) leads to three recursive calls; when all calls
are still active, the runtime stack would be as shown below (showing just
the values of parameter N).
The values returned by each call are also shown.
Returned value
+------+ --------------
| N: 0 | <--- top of stack 1
+------+
+------+
| N: 1 | 1
+------+
+------+
| N: 2 | 2
+------+
+------+
| N: 3 | 6
+------+
Question 2:
The iterative version of factorial will return 1 as the result of the call
factorial(-1).
The recursive version will go into an infinite recursion (because the base
case, N==0, will enver be reached).
Since, mathematically, factorial is undefined for negative numbers,
a call to factorial with a negative number should cause an exception.
This is easily done for the iterative version:
int factorial (int N) throws NegativeValueException {
if (N < 0)throw new NegativeValueException();
if (N == 0) return 1;
int tmp = 1;
for (int k=N; k>1; k--) tmp = tmp*k;
return (tmp);
}
(where NegativeValueException would have to be defined as a public exception).
For the recursive version, we could change the method to:
int factorial (int N) throws NegativeValueException {
if (N < 0)throw new NegativeValueException();
if (N == 0) return 1;
else return (N*factorial(N-1));
}
However, the problem with this is that the check for N < 0 will be made
on every call, including the recursive calls where it cannot be true.
This makes the method slightly less efficient.
A better solution would be to make the check once, the first time
factorial is called, and then use an auxiliary, recusive method with no
check:
int factorial (int N) throws NegativeValueException {
if (N < 0)throw new NegativeValueException();
else return factAux(N);
}
private int factAux(int N) {
if (N == 0) return 1;
else return (N*factAux(N-1));
}