This may not have as much relevance in this case (because the factor value - and consequently the superfatorial - grows so fast that it is impracticable to calculate it for large numbers), but the way you and the other respondents are calculating has an inefficiency, which is to calculate again and again components used in various parts of the calculation (as already pointed out by user2856432). When calculating 4!
for example you already calculate 3!
, best use this result after calculating 3!
again in the next term. The complexity in the case is quadratic with the argument value.
I’m going to show you an alternative here, not so much because of the problem itself (which, as I said, is impossible 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, in case it is not clear what the code is doing:
- The initial call passes
0! = 1
as accumulator, and the interval 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 accumulator n*(n-1)! = 1*(1-1)! = 1*0! = 1!
;
- 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 as accumulator n*(n-1)! = 2*(2-1)! = 2*1! = 2!
;
- 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 accumulator n*(n-1)! = 3*(3-1)! = 3*2! = 3!
;
- The result is
0! * 1! * 2! * sfat(2)
- ...
- The umpteenth 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 stopping 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 argument value.
Note: if you wanted to implement the tail recursion - where the recursive call is the last executed operation (useful in languages whose compiler optimizes this type of call, turning it into iterative) - you could do this through two accumulators: one for the factorial, and the other pro 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 the ideone.
Two tags from two different languages, the problem can be solved in either of the two?
– DaviAragao
Do you have to do everything in a single function or can it be two? For example, a factorial and superfatorial?
– Bruno César
The idea of exercise is this.
– MSX
calls it
superaux
and creates another functionint super(int n){ return superaux(n,n);}
– JJoao