Section courante

A propos

Section administrative du site

Les nombres de Fibonacci

Les nombres de Fibonacci forment une suite d'entiers dans laquelle chaque terme est obtenu en additionnant les deux termes qui le précèdent. Cette suite constitue l'un des exemples les plus connus de définition récursive et occupe une place importante en mathématiques appliquées, en algorithmique, en combinatoire, en théorie des nombres et en programmation.

En informatique, la suite de Fibonacci est souvent utilisée pour expliquer la récursivité, la programmation dynamique, la mémorisation, l'analyse de complexité et les méthodes de calcul matriciel. Elle permet de comparer plusieurs approches produisant le même résultat, mais dont les performances peuvent être radicalement différentes.

Les nombres de Fibonacci apparaissent également dans des problèmes de dénombrement, dans l'étude des structures arborescentes, dans certaines méthodes de recherche et dans des structures de données comme les tas de Fibonacci. Leur relation avec le nombre d'or, les coefficients binomiaux et les fonctions génératrices en fait une notion centrale des fondements mathématiques de la programmation.

Historique

La suite porte le nom de Leonardo de Pise, plus connu sous le nom de Fibonacci, un mathématicien italien ayant vécu aux XIIe et XIIIe siècles. Il la présenta en Europe dans son ouvrage Liber Abaci, publié en 1202, à travers un problème théorique portant sur la reproduction d'une population de lapins.

Cependant, des suites équivalentes étaient connues bien avant Fibonacci, notamment dans les mathématiques indiennes, où elles apparaissaient dans l'étude des rythmes et des combinaisons de syllabes longues et courtes.

Le mérite de Fibonacci réside principalement dans la diffusion de cette suite dans les mathématiques européennes. Depuis, elle est devenue un exemple classique dans l'enseignement de l'algorithmique et de la récursivité.

Définition

La suite de Fibonacci est généralement définie par :

F0 = 0
F1 = 1

et, pour tout entier :

n ≥ 2

par la relation :

Fn = Fn-1 + Fn-2

Chaque terme est donc égal à la somme des deux termes précédents.

Les premiers nombres de Fibonacci sont :

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

Convention commençant par 1

Certaines documentations présentent la suite sous la forme :

1, 1, 2, 3, 5, 8, 13, 21, ...

Cette convention utilise généralement :

F1 = 1
F2 = 1

Elle décrit la même suite, mais avec des indices décalés.

En programmation, il est important de préciser la convention utilisée, car :

F0 = 0

dans la définition moderne la plus courante, tandis que certaines bibliothèques ou certains exercices commencent directement à :

F1 = 1

Construction de la suite

Les premiers termes sont obtenus comme suit :

F0 = 0
F1 = 1

Puis :

F2 = F1 + F0
   = 1 + 0
   = 1
F3 = F2 + F1
   = 1 + 1
   = 2
F4 = F3 + F2
   = 2 + 1
   = 3
F5 = F4 + F3
   = 3 + 2
   = 5
F6 = F5 + F4
   = 5 + 3
   = 8

Le même principe est appliqué pour produire tous les termes suivants.

Premières valeurs

n Fn
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
15 610
20 6 765
30 832 040
40 102 334 155
50 12 586 269 025

La croissance des nombres de Fibonacci est rapide, bien qu'elle soit moins importante que celle de la fonction factorielle.

Définition récursive

La définition mathématique de la suite se traduit directement par un algorithme récursif.

MODULE Fibonacci(n)

   SI n = 0 ALORS
      RETOURNER 0
   FIN SI

   SI n = 1 ALORS
      RETOURNER 1
   FIN SI

   RETOURNER
      Fibonacci(n - 1)
      +
      Fibonacci(n - 2)

Cet algorithme est très simple et reproduit exactement la définition mathématique.

Cependant, il est extrêmement inefficace pour les grandes valeurs de n.

Arbre des appels récursifs

Pour calculer :

Fibonacci(5)

l'algorithme calcule :

Fibonacci(4) + Fibonacci(3)

Puis :

Fibonacci(4)

demande :

Fibonacci(3) + Fibonacci(2)

et :

Fibonacci(3)

est à nouveau recalculé dans une autre branche.

Une représentation simplifiée est :

Plusieurs valeurs sont donc calculées de nombreuses fois.

Complexité de la récursion naïve

L'algorithme récursif naïf produit un nombre d'appels qui augmente exponentiellement.

Sa complexité temporelle est souvent exprimée par :

O(2n)

Une estimation plus précise est :

O(φn)

où φ représente le nombre d'or.

La profondeur maximale de récursion est proportionnelle à :

n

La complexité mémoire liée à la pile d'appels est donc :

O(n)

Cette méthode est principalement utile pour illustrer la récursivité, mais elle ne devrait pas être utilisée pour des calculs importants.

Algorithme itératif

Une méthode beaucoup plus efficace consiste à calculer les termes successivement en conservant uniquement les deux valeurs précédentes.

MODULE Fibonacci(n)

   SI n = 0 ALORS
      RETOURNER 0
   FIN SI

   précédent ← 0
   courant ← 1

   BOUCLE POUR i ← 2 JUSQU'A n
      suivant ← précédent + courant
      précédent ← courant
      courant ← suivant
   FIN BOUCLE POUR
   RETOURNER courant

Cette méthode évite les calculs répétés.

Exemple d'exécution

Pour calculer :

F6

les variables évoluent ainsi :

Itération précédent courant suivant
Initialisation 0 1 -
2 1 1 1
3 1 2 2
4 2 3 3
5 3 5 5
6 5 8 8

Le résultat final est :

F6 = 8

Complexité de la méthode itérative

La boucle effectue approximativement n itérations.

La complexité temporelle est donc :

O(n)

Seules quelques variables sont utilisées, indépendamment de la valeur de n.

La complexité mémoire supplémentaire est :

O(1)

Cette méthode est simple, rapide et adaptée à la majorité des applications courantes.

Exemple en Java

  1. public class FibonacciSample {
  2.  
  3.     public static long fibonacci(int n) {
  4.         if (n < 0) {
  5.             throw new IllegalArgumentException(
  6.                 "L'indice doit être positif ou nul."
  7.             );
  8.         }
  9.  
  10.         if (n == 0) {
  11.             return 0;
  12.         }
  13.  
  14.         long precedent = 0;
  15.         long courant = 1;
  16.  
  17.         for (int i = 2; i <= n; i++) {
  18.             long suivant = precedent + courant;
  19.             precedent = courant;
  20.             courant = suivant;
  21.         }
  22.  
  23.         return courant;
  24.     }
  25.  
  26.     public static void main(String[] args) {
  27.         for (int i = 0; i <= 10; i++) {
  28.             System.out.println(
  29.                 "F" + i + " = " + fibonacci(i)
  30.             );
  31.         }
  32.     }
  33. }

Le programme affiche :

F0 = 0
F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55

Mémorisation

La mémorisation consiste à conserver les résultats déjà calculés afin d'éviter de les recalculer.

MODULE Fibonacci(n, mémoire)

   SI n existe dans mémoire ALORS
      RETOURNER mémoire[n]
   FIN SI

   SI n = 0 ALORS
      RETOURNER 0
   FIN SI

   SI n = 1 ALORS
      RETOURNER 1
   FIN SI

   mémoire[n] ←
      Fibonacci(n - 1, mémoire)
      +
      Fibonacci(n - 2, mémoire)

   RETOURNER mémoire[n]

Chaque valeur comprise entre 0 et n n'est calculée qu'une seule fois.

Complexité avec mémorisation

La mémorisation réduit la complexité temporelle à :

O(n)

La mémoire utilisée pour conserver les résultats et la pile récursive est :

O(n)

Cette méthode conserve la structure récursive tout en éliminant les calculs redondants.

Elle constitue un exemple classique de programmation dynamique descendante, également appelée approche top-down.

Programmation dynamique ascendante

Une autre approche consiste à remplir un tableau dans l'ordre croissant des indices.

MODULE Fibonacci(n)

   Créer tableau F[0..n]

   F[0] ← 0

   SI n ≥ 1 ALORS
      F[1] ← 1
   FIN SI

   BOUCLE POUR i ← 2 JUSQU'A n
      F[i] ← F[i - 1] + F[i - 2]
   FIN BOUCLE POUR

   RETOURNER F[n]

Cette méthode est appelée programmation dynamique ascendante, ou bottom-up.

Sa complexité temporelle est :

O(n)

et sa complexité mémoire est :

O(n)

Elle est utile lorsque plusieurs termes de la suite doivent être conservés ou réutilisés.

Calcul matriciel

La relation de Fibonacci peut être exprimée à l'aide de matrices :

| Fn+1 |   | 1  1 | | Fn   |
| Fn   | = | 1  0 | | Fn-1 |

On peut donc écrire :

| Fn+1  Fn   |
| Fn    Fn-1 |
=
| 1  1 |n
| 1  0 |

Le calcul de la puissance de cette matrice par exponentiation rapide permet d'obtenir F? en un nombre logarithmique d'étapes.

Exponentiation rapide de matrices

L'exponentiation rapide repose sur les propriétés suivantes :

Mn = (Mn/2)2

lorsque n est pair, et :

Mn = M × Mn-1

lorsque n est impair.

Le nombre d'étapes nécessaires est proportionnel à :

log n

La complexité temporelle du calcul matriciel est donc :

O(log n)

si l'on considère les opérations arithmétiques élémentaires comme ayant un coût constant.

Méthode du doublement rapide

La méthode du doublement rapide, ou fast doubling, permet de calculer directement deux termes consécutifs.

Elle repose sur les identités :

F2k = Fk × (2Fk+1 - Fk)

et :

F2k+1 = Fk2 + Fk+12

Ces identités permettent de diviser l'indice par deux à chaque étape.

Algorithme du doublement rapide

MODULE FibonacciDoublement(n)

   SI n = 0 ALORS
      RETOURNER (0,1)
   FIN SI

   (a,b) ← FibonacciDoublement(n DIV 2)

   c ← a × (2 × b - a)
   d ← a × a + b × b

   SI n est pair ALORS
      RETOURNER (c,d)
   SINON
      RETOURNER (d,c+d)
   FIN SI

La paire retournée contient :

(Fn,Fn+1)

La complexité temporelle est :

O(log n)

Cette méthode est généralement plus simple et plus efficace que la multiplication de matrices complète.

Exemple en Java avec BigInteger

  1. import java.math.BigInteger;
  2.  
  3. public class FibonacciRapideSample {
  4.  
  5.     public static BigInteger[] fibonacci(
  6.         long n
  7.     ) {
  8.         if (n == 0) {
  9.             return new BigInteger[] {
  10.                 BigInteger.ZERO,
  11.                 BigInteger.ONE
  12.             };
  13.         }
  14.  
  15.         BigInteger[] paire =
  16.             fibonacci(n / 2);
  17.  
  18.         BigInteger a = paire[0];
  19.         BigInteger b = paire[1];
  20.  
  21.         BigInteger c = a.multiply(
  22.             b.shiftLeft(1).subtract(a)
  23.         );
  24.  
  25.         BigInteger d = a.multiply(a)
  26.             .add(b.multiply(b));
  27.  
  28.         if (n % 2 == 0) {
  29.             return new BigInteger[] {c, d};
  30.         }
  31.  
  32.         return new BigInteger[] {
  33.             d,
  34.             c.add(d)
  35.         };
  36.     }
  37.  
  38.     public static void main(String[] args) {
  39.         System.out.println(
  40.             "F100 = " + fibonacci(100)[0]
  41.         );
  42.     }
  43. }

Le programme affiche :

F100 = 354224848179261915075

L'utilisation de BigInteger permet de calculer des termes dépassant la capacité des entiers de 64 bits.

Formule de Binet

Le nombre de Fibonacci d'indice n peut également être calculé par une formule fermée appelée formule de Binet :

Fn =
n - ψn) / √5

où :

Fn =
ψ = (1 + √5) / 2

et :

Ψ = (1 - √5) / 2

Le nombre Φ est appelé nombre d'or.

Comme la valeur absolue de Ψ est inférieure à 1, le terme Ψn devient très petit lorsque n augmente.

Approximation avec le nombre d'or

Pour les valeurs suffisamment grandes de n, on peut écrire :

Fn ≈ φn / √5

Le terme exact peut être obtenu en arrondissant cette valeur à l'entier le plus proche :

Fn =
Arrondi(Φn / √5)

Cette relation montre que la croissance de la suite est essentiellement exponentielle.

En notation asymptotique :

Fn = Θ(φn)

Limites de la formule de Binet

La formule de Binet paraît permettre un calcul en temps constant. Toutefois, son utilisation avec des nombres à virgule flottante présente plusieurs limites :

Cette formule est donc surtout utile pour les démonstrations, les approximations et l'étude de la croissance de la suite.

Relation avec le nombre d'or

Le rapport de deux termes consécutifs tend vers le nombre d'or :

Fn+1 / Fn → φ

lorsque :

n → ∞

Quelques rapports sont :

F5 / F4 = 5 / 3 ≈ 1,666667
F10 / F9 = 55 / 34 ≈ 1,617647
F20 / F19 =
6765 / 4181
≈ 1,618034

La valeur du nombre d'or est approximativement :

φ ≈ 1,6180339887

Propriétés de divisibilité

Les nombres de Fibonacci possèdent plusieurs propriétés arithmétiques remarquables.

Si m divise n, alors :

Fm divise Fn

Par exemple :

4 divise 8

et :

F4 = 3

divise :

F8 = 21

De plus :

PGCD(Fm,Fn) =
FPGCD(m,n)

Par exemple :

PGCD(F8,F12)
=
F4
=
3

car :

PGCD(8,12) = 4

Identité de Cassini

L'identité de Cassini établit que :

Fn+1Fn-1 - Fn2 = (-1)n

Par exemple, pour :

n = 5

on obtient :

F6F4 - F52

soit :

8 × 3 - 52

donc :

24 - 25 = -1

Comme 5 est impair :

(-1)5 = -1

L'identité est donc vérifiée.

Somme des nombres de Fibonacci

La somme des termes de F0 à Fn est :

i=0n Fi =
Fn+2 - 1

Par exemple :

F0 + F1 + F2 + F3 + F4 + F5

donne :

0 + 1 + 1 + 2 + 3 + 5 = 12

Or :

F7 - 1 = 13 - 1 = 12

Somme des carrés

La somme des carrés des premiers termes satisfait :

i=0n Fi2 =
FnFn+1

Par exemple, pour :

n = 5

on obtient :

02 + 12 + 12 + 22 + 32 + 52

soit :

0 + 1 + 1 + 4 + 9 + 25 = 40

Et :

F5F6 = 5 × 8 = 40

Relation avec les coefficients binomiaux

Les nombres de Fibonacci peuvent être exprimés à l'aide de coefficients binomiaux :

Fn =
k=0⌊(n-1)/2⌋
C(n-k-1,k)

Par exemple, pour :

n = 6

on obtient :

F6 =
C(5,0) + C(4,1) + C(3,2)

soit :

1 + 4 + 3 = 8

Cette identité montre le lien entre la suite de Fibonacci et les problèmes de dénombrement.

Interprétation combinatoire

Les nombres de Fibonacci peuvent compter le nombre de façons de parcourir une distance avec des pas de longueur 1 ou 2.

Supposons qu'un escalier contient n marches et qu'une personne peut monter :

Le nombre de façons d'atteindre la marche n satisfait :

M(n) = M(n-1) + M(n-2)

car le dernier déplacement est nécessairement :

Cette relation est identique à celle de Fibonacci.

Exemple de l'escalier

Pour un escalier de quatre marches, les parcours possibles sont :

1 + 1 + 1 + 1
1 + 1 + 2
1 + 2 + 1
2 + 1 + 1
2 + 2

Il existe donc 5 possibilités.

Avec la convention appropriée :

M(4) = F5 = 5

Ce type de problème constitue un exemple classique de programmation dynamique.

Pavages d'une bande

Les nombres de Fibonacci comptent également le nombre de façons de recouvrir une bande de longueur n avec :

Le dernier élément du pavage est soit :

Le nombre de pavages satisfait donc la même relation de récurrence.

Chaînes binaires sans deux 1 consécutifs

Le nombre de chaînes binaires de longueur n ne contenant pas deux bits 1 consécutifs est lié aux nombres de Fibonacci.

Par exemple, pour une longueur de 3, les chaînes autorisées sont :

000
001
010
100
101

Il existe cinq chaînes.

Ce nombre correspond à :

F5 = 5

De manière générale, le nombre de chaînes binaires de longueur n sans deux 1 consécutifs est :

Fn + 2

Recherche de Fibonacci

La recherche de Fibonacci est une méthode permettant de rechercher une valeur dans un tableau trié.

Elle divise le tableau à l'aide de nombres de Fibonacci plutôt qu'en utilisant directement le milieu comme la recherche binaire.

Son principe consiste à comparer la valeur recherchée avec un élément situé à une position déterminée par un nombre de Fibonacci, puis à réduire progressivement l'intervalle de recherche.

Sa complexité temporelle est :

O(log n)

Elle peut être utile lorsque l'accès séquentiel est moins coûteux que certains accès aléatoires, bien que la recherche binaire soit généralement plus courante.

Tas de Fibonacci

Un tas de Fibonacci est une structure de données composée d'une collection d'arbres respectant une propriété de tas.

Cette structure permet notamment :

Les tas de Fibonacci sont utilisés dans certains algorithmes de graphes, notamment les variantes théoriquement optimisées de l'algorithme de Dijkstra et de l'algorithme de Prim.

Leur nom vient de l'utilisation des nombres de Fibonacci dans l'analyse de la taille minimale des arbres qu'ils contiennent.

Suite modulo un entier

Lorsqu'on calcule les nombres de Fibonacci modulo un entier m, les valeurs finissent par se répéter périodiquement.

La suite :

Fn MOD m

possède une période appelée période de Pisano.

Par exemple, modulo 2, la suite devient :

0, 1, 1, 0, 1, 1, 0, ...

Sa période est donc :

3

Cette propriété est utile dans les calculs modulaires portant sur de très grands indices.

Dépassement de capacité

Les nombres de Fibonacci croissent rapidement.

Pour un entier signé de 32 bits, la plus grande valeur représentable de la suite est :

F46 = 1836311903

Le terme suivant :

F47 = 2971215073

dépasse la capacité maximale d'un entier signé de 32 bits.

Pour un entier signé de 64 bits, la plus grande valeur représentable est :

F92 =
7540113804746346429

Le terme :

F93 =
12200160415121876738

dépasse cette capacité.

Pour les indices supérieurs, il faut utiliser des entiers multiprécision.

Nombres négatifs

La suite peut être étendue aux indices négatifs.

Ces valeurs sont appelées nombres de Fibonacci négatifs ou négafibonacci.

La relation est :

F-n = (-1)n+1Fn

Par exemple :

F-1 = 1
F-2 = -1
F-3 = 2
F-4 = -3
F-5 = 5

Les signes alternent, tandis que les valeurs absolues restent celles de la suite ordinaire.

Fonction génératrice

La fonction génératrice ordinaire de la suite de Fibonacci est :

G(x) =
F0 + F1x + F2x2 + F3x3 + ...

Elle est donnée par :

G(x) = x / (1 - x - x2)

Cette expression permet d'étudier algébriquement la suite, de retrouver sa relation de récurrence et de démontrer plusieurs identités.

Les fonctions génératrices seront abordées plus en détail dans une section distincte.

Comparaison des méthodes de calcul

Méthode Temps Mémoire Caractéristique
Récursion naïve O(φn) O(n) Simple, mais très lente
Récursion mémorisée O(n) O(n) Conserve la récursivité
Programmation dynamique O(n) O(n) Conserve tous les termes
Méthode itérative O(n) O(1) Simple et efficace
Calcul matriciel O(log n) O(log n) ou O(1) Adapté aux grands indices
Doublement rapide O(log n) O(log n) Très efficace
Formule de Binet Théoriquement courte O(1) Risques d'arrondi

Pour les calculs exacts de grands nombres de Fibonacci, la méthode du doublement rapide associée à des entiers multiprécision constitue généralement un excellent choix.

Complexité arithmétique réelle

Lorsque les valeurs deviennent très grandes, une addition n'a plus un coût constant.

Le nombre de bits de Fn est proportionnel à :

n

car :

Fn ≈ φn / √5

Les opérations sur ces grands entiers deviennent donc progressivement plus coûteuses.

Ainsi, les complexités comme :

O(n)

ou :

O(log n)

comptent généralement le nombre d'opérations arithmétiques, mais ne représentent pas toujours le coût exact de la manipulation de nombres multiprécision.

Applications

Les nombres de Fibonacci sont utilisés dans de nombreux domaines :

Ils servent également d'exemple pour comparer différentes stratégies algorithmiques.

Avantages

Les nombres de Fibonacci présentent plusieurs avantages pédagogiques et pratiques :

Limites et précautions

Plusieurs précautions doivent être prises :

Remarque

Les nombres de Fibonacci constituent un exemple particulièrement riche de relation entre une définition mathématique simple et des problèmes algorithmiques complexes. Une implémentation récursive directe peut nécessiter un temps exponentiel, tandis qu'une méthode itérative réduit ce coût à un temps linéaire et que le doublement rapide permet d'atteindre un temps logarithmique en nombre d'étapes. Cette différence illustre l'importance du choix de l'algorithme, même lorsque la formule mathématique de départ paraît élémentaire.

La suite relie également la récursivité, la programmation dynamique, le nombre d'or, les coefficients binomiaux, le calcul matriciel et les fonctions génératrices. Elle constitue ainsi une excellente transition vers l'étude des fonctions génératrices, lesquelles permettent de représenter et d'analyser des suites numériques à l'aide de séries formelles.



Dernière mise à jour : Jeudi, le 16 juillet 2026