Vous êtes sur la page 1sur 4

Stage IREM : Initiation à l’algorithmique

TP 2 : Suite de Fibonacci

Groupe Algorithmique, IREM de Paris


24 mars 2015

On rappelle la définition de la suite de Fibonacci :



f0 = 0,

f1 = 1,

fn = fn−1 + fn−2 pour n ≥ 2.

L’objectif de cette fiche d’activité est d’implémenter plusieurs algorithmes de


calcul du n-ème terme de cette suite, et de les comparer entre eux (notamment
leur complexité algorithmique “théorique” et leur performance en pratique).

1 Algorithmes simples

x Exercice 1 : Algorithme naı̈f.


1. En appliquant directement la définition de la suite de Fibonacci, écrivez
une fonction récursive fibo_naif(n) calculant le terme fn .
Indication : cette fonction doit effectuer deux appels récursifs.
2. Modifiez la fonction pour qu’elle renvoie, en plus de la valeur de fn , le
nombre d’additions effectuées par le calcul. Expérimentez sur quelques
valeurs, puis vérifiez le résultat à la main sur une petite valeur de n (par
exemple 5).
3. À l’aide de la fonction time() du module time, qui renvoie (en secondes)
l’heure au moment où elle est appelée, déterminez le plus petit entier n tel
que le temps de calcul de cette fonction dépasse 1/10000s, puis 1/1000s.
Que constatez-vous?
4. Encadrez la complexité asymptotique en nombre d’opérations (par
exemple d’additions) de la fonction fibo_naif.
Indication : on pourra définir une suite T1 (n) dont le n-ème terme est le
temps de calcul de la fonction fibo_naif sur le paramètre n.

x Exercice 2 : Algorithme récursif efficace.


En calculant simultanément fn et fn−1 , on peut rendre le calcul plus efficace.
En effet, si ces deux termes sont connus, il est très simple de calculer fn+1 .
1. Écrivez une fonction fibo_rec(n) renvoyant le couple d’entiers (fn ,fn−1 ).
Chaque appel à la fonction doit effectuer au plus un appel récursif.
2. Vérifiez les résultats obtenus en les comparant à ceux de la fonction
précédente (pour des valeurs raisonnables de n).

1
3. Reprenez la question 2 de l’exercice précédent pour la fonction fibo_rec.
4. Reprenez la question 3 de l’exercice précédent. Que constatez-vous? Cher-
chez la plus petite valeur de n pour laquelle le temps de calcul dépasse
0,1s. Que se passe-t-il?
5. Reprenez la question 4 de l’exercice précédent.

x Exercice 3 : Algorithme itératif efficace.


On veut implémenter la même idée que dans la solution précédente mais de
manière itérative. À l’aide de deux variables, on mémorisera à tout moment les
valeurs des deux derniers termes connus de la suite.
1. Implémentez une fonction fibo_iter(n) selon cette idée.
2. Vérifiez les résultats des calculs en les comparant à ceux des fonctions
précédentes.
3. Reprenez les questions 2 à 4 de l’exercice 1.
4. Comment expliquez-vous la différence de performance entre les fonctions
fibo_rec et fibo_iter?

2 Passage par les nombres flottants


Avant de pouvoir implémenter une fonction de calcul de la suite de Fibo-
nacci à l’aide des nombres flottants, nous allons implémenter plusieurs fonctions
calculant la puissance entière d’un nombre flottant.

x Exercice 4 : Calcul de puissance.


On souhaite écrire une fonction calculant une valeur proche de an pour un
nombre réel a et un nombre entier positif n donnés. Pour cela, on se munit des
définitions suivantes
( de an :
n−1
a∗a si n > 0,
1. an =
1 si n = 0.

bn/2c 2
(a
 ) si n > 0 est pair,
2. an = a ∗ (abn/2c )2 si n est impair,

1 si n = 0.

Programmez deux fonctions puiss_lente(a, n) et puiss_rapide(a, n)
implémentant chacune de ces deux définitions, puis exprimez leur complexité
asymptotique.

x Exercice 5 : Fibonacci par les flottants.


On peut donner une expression fonctionnelle du terme fn (c’est-à-dire non
récursive mais dépendant uniquement de n) par une analyse mathématique de la
suite. En résolvant le polynôme caractéristique de cette suite (récurrente d’ordre
2), on peut déterminer que ses termes sont de la forme
√ √
1 n 1+ 5 1− 5
fn = √ (ϕn − ϕ0 ) avec ϕ = et ϕ0 = .
5 2 2
(Vous avez reconnu ϕ, le nombre d’or.)
Comme ϕn tend vers +∞ et ϕ0n vers 0 quand n tend vers +∞, le second
terme de cette expression devient négligeable à partir d’un certain rang (en fait

2
dès n = 1), et on peut calculer fn simplement en arrondissant √15 ϕn à l’entier le
plus proche. Cela nous fournit un nouveau moyen pour calculer fn efficacement.

1. Retrouvez la démonstration des résultats annoncés ci-dessus.


2. Écrivez une fonction fibo_phi_lent exploitant cette idée. Cette fonction
utilisera la fonction puiss_lente de l’exercice précédent.
3. Écrivez une fonction fibo_phi_rapide utilisant la fonction puiss_rapide
de l’exercice précédent.
4. Écrivez une fonction fibo_phi_natif utilisant l’opérateur puissance (**)
de Python.
5. Comparez les performances de ces trois fonctions sur des valeurs crois-
santes de n.
6. Exprimez la complexité asymptotique en temps des fonctions
fibo_phi_lent et fibo_phi_rapide, et conjecturez celle de l’opérateur
**.
7. Calculez les valeurs renvoyées par ces fonctions pour n = 100 et comparez-
les aux résultats précédents. Que constatez-vous ? Comment l’expliquez-
vous?
8. Calculez les valeurs renvoyées par ces fonctions pour n = 1500. Que
constatez-vous? Comment l’expliquez-vous?

3 Passage par le calcul matriciel


On a vu que le passage par les nombres flottants, malgré une performance
très bonne, posait d’autres problèmes. Comment faire pour calculer fn avec
précision pour une grande valeur de n?

x Exercice 6 :
La définition de la suite de Fibonacci peut se reformuler selon la définition
matricielle suivante :
     
fn 1 1 fn−1
= × pour tout n ≥ 2
fn−1 1 0 fn−2

où bien sûr on a toujours f0 = 0 et f1 = 1. On peut facilement en déduire


l’égalité suivante (toujours pour n ≥ 2) :
 n−1  
1 1 fn fn−1
=
1 0 fn−1 fn−2

1. Écrivez une fonction produit_2x2(m1, m2) calculant la matrice produit


des deux matrices carrées de dimension 2 mat1 et mat2 (ou, si cela vous
amuse, une fonction produit_matrice calculant le produit de deux ma-
trices de dimensions m × n et n × p quelconques).
2. À l’aide de cette fonction, écrivez une fonction puissance_2x2(mat, n)
calculant la puissance n-ème rapide de la matrice 2 × 2 mat.
 0  
a b 1 0
Rappel : = .
c d 0 1
3. À l’aide de cette fonction, écrivez une fonction fibo_mat(n) calculant fn .

3
4. Comparez les résultats et les performances de cette fonction avec les
précédentes.
5. À partir de quel rang la fonction fibo_mat est-elle plus rapide que la
fonction fibo_rec? que la fonction fibo_iter?
6. Exprimez la complexité asymptotique théorique de cette fonction.
7. Comment expliquez-vous que ses performances réelles soient à ce point
pires que toutes les autres fonctions pour n petit, et que les fonctions
fibo_phi pour n plus grand?
8. Cette méthode effectue-t-elle des calculs inutiles ? Quelles améliorations
peut-on envisager?