public class Iter2Rec {
public static void calcul(int n) {
System.out.println(n);
}
// Un calcul itératif (répétition d'un calcul pour chaque valeur de la
// variable d'itération)
public static void fIter() {
for (int i=0; i<10; i++) {
calcul(i);
}
}
// L'itération peut être traduite en récursion (terminale)
// Récursion terminale: appel récursif immédiatement suivi d'un retour
public static void fRec(int i) {
if (i<10) {
calcul(i);
fRec(i+1); // appel récursif terminal
return;
}
}
// Mais dans l'autre sens: passer d'une récursion à une itération ?
// Pas possible dans le cas général, mais dans le cas particulier
// de la factorielle, ça devrait...
// Définition récursive (non terminale)
public static int fact(int n) {
if (n==0) return 1;
return n*fact(n-1);
}
// Explicitation du caractère non terminal de l'appel récursif
// Entre l'appel et la retour, il y a des calculs à faire (la multiplication)
public static int fact2(int n) {
System.out.println("fact2("+n+")");
if (n==0) return 1;
int r = fact2(n-1);
r = n*r;
System.out.println("retour="+r);
return r;
}
// En utilisant la propriété de commutation de la multiplication on doit
// pouvoir transformer les calculs effectués en remontant (1*2*3*4...)
// par des calculs descendants (n*(n-1)*(n-2)...)
public static int fact2accumulee(int n,int r) {
System.out.println("fact2accumulee("+n+","+r+")");
if (n==0) return r;
r = n*r;
return fact2accumulee(n-1,r); // appel récursif terminal!
}
// On peut donc éliminer l'appel puisque rien ne se passe entre
// l'appel et le retour, les variables peuvent être librement réutilisées
// on transforme donc n en n-1 puis on fait une boucle arrière au début de
// la fonction
public static int fact2accumuleeIter(int n,int r) {
while (true) {
if (n==0) return r;
r = n*r;
n = n-1;
}
// return fact2accumuleeIter(n-1,r);
}
public static void main(String []a) {
fIter();
fRec(0);
fact2(6);
fact2accumulee(6,1);
System.out.println("Par iteration="+fact2accumuleeIter(6,1));
}
}