This may not be so relevant in this case (because the factorial value - and consequently the superfactor value - grows so fast that it is unfeasible to calculate it for large numbers), but how you and the other respondents are calculating has a inefficiency, which is to calculate again and again components used in various parts of the calculation (as pointed out by user2856432). When calculating 4!
for example you already calculate 3!
, best to use this result after calculating 3!
again in the next term. The complexity in the case is quadratic with the value of the argument.
I will show an alternative here, not so much by the problem itself (which as I said, it is not feasible to do for large numbers) but to demonstrate a very useful technique when working with recursion - the accumulator :
int sfat(n) {
return sfat2(1, n, 1); // Vai de 1 a n, e o valor acumulado é 1
}
int sfat2(inicio, fim, acumulador) {
if ( inicio > fim )
return acumulador;
return acumulador * sfat2(inicio+1, fim, inicio*acumulador);
}
Explaining, if it is not clear what the code is doing:
- The initial call passes
0! = 1
as accumulator, and the range goes from 1
to n
;
- The first call - term
1
- multiplies this (n-1)! = (1-1)! = 0!
by the result of the recursive call, which in turn receives as n*(n-1)! = 1*(1-1)! = 1*0! = 1!
accumulator;
- The result is
0! * sfat(1)
- The second call - term
2
- multiplies this (n-1)! = (2-1)! = 1!
by the result of the recursive call, which in turn receives n*(n-1)! = 2*(2-1)! = 2*1! = 2!
as accumulator;
- The result is
0! * 1! * sfat(2)
- The third call - term
3
- multiplies this (n-1)! = (3-1)! = 2!
by the result of the recursive call, which in turn receives as n*(n-1)! = 3*(3-1)! = 3*2! = 3!
accumulator;
- The result is
0! * 1! * 2! * sfat(2)
- ...
- The nth call - term
n
- multiplies this (n-1)!
by the result of the recursive call, which in turn receives as accumulator n*(n-1)!
;
- The result is
0! * 1! * 2! * ... * (n-1)! * sfat(n+1)
- The next call - term
n+1
- finds the stop condition, returning the accumulator ((n+1) - 1)! = n!
;
- The result is
0! * 1! * 2! * ... * (n-1)! * n!
As you can see, the number of recursive calls is now linear with the value of the argument.
Note : If you wanted to implement tail recursion - where the recursive call is the last executed operation (useful in languages whose compiler optimizes this type of call, transforming it into iterative) - you could do this through two accumulators: one for the factorial, and another for result:
int sfat(n) {
return sfat2(1, n, 1, 1); // Acumula (n-1)! e o resultado
}
int sfat2(inicio, fim, fat_acc, sfat_acc) {
if ( inicio > fim )
return sfat_acc;
return sfat2(inicio+1, fim, inicio*fat_acc, inicio*fat_acc*sfat_acc);
}
Examples in ideone .