Voici une fonction en C qui implémente la suite définie par , , et pour tout :
#include <stdio.h> // Fonction pour calculer le n-ième terme de la suite int suite(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { int U_n_2 = 0; // U(0) int U_n_1 = 1; // U(1) int U_n; for (int i = 2; i <= n; i++) { U_n = 3 * U_n_1 - U_n_2; U_n_2 = U_n_1; U_n_1 = U_n; } return U_n; } } int main() { int n; printf("Entrez la valeur de n : "); scanf("%d", &n); if (n < 0) { printf("La valeur de n doit être un entier positif ou nul.\n"); } else { int resultat = suite(n); printf("U(%d) = %d\n", n, resultat); } return 0; }
Fonction suite
:
n
en entrée et retourne le n-ième terme de la suite.n
est 0, elle retourne 0.n
est 1, elle retourne 1.n
supérieures ou égales à 2, elle utilise une boucle pour calculer les termes de la suite en utilisant la relation de récurrence .Fonction main
:
n
.n
est un entier positif ou nul.suite
pour calculer le n-ième terme de la suite et affiche le résultat.Vous pouvez compiler et exécuter ce programme pour voir les termes de la suite pour différentes valeurs de n
.
Si on appelle la fonction suite
pour des valeurs de plus en plus grandes, on peut observer plusieurs phénomènes intéressants :
Croissance rapide des valeurs :
Dépassement de capacité :
int
) ont une plage de valeurs limitée. Par exemple, un int
sur une machine 32 bits peut représenter des valeurs allant de -2,147,483,648 à 2,147,483,647. Pour des valeurs de suffisamment grandes, les termes de la suite peuvent dépasser cette plage, ce qui entraîne un dépassement de capacité (overflow). Cela peut conduire à des résultats incorrects ou à un comportement imprévisible du programme.Temps de calcul :
Pour illustrer, voici quelques termes de la suite pour des valeurs croissantes de :
On voit que les valeurs augmentent très rapidement. Pour des valeurs de au-delà de 30 ou 40, les termes de la suite peuvent dépasser la capacité d'un int
en C.
Utiliser des types de données plus grands :
long long
en C, qui peuvent représenter des valeurs plus grandes.Utiliser des bibliothèques de calcul en précision arbitraire :
Vérifier les dépassements de capacité :
Voici un exemple de modification de la fonction pour utiliser long long
:
#include <stdio.h> // Fonction pour calculer le n-ième terme de la suite long long suite(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { long long U_n_2 = 0; // U(0) long long U_n_1 = 1; // U(1) long long U_n; for (int i = 2; i <= n; i++) { U_n = 3 * U_n_1 - U_n_2; U_n_2 = U_n_1; U_n_1 = U_n; } return U_n; } } int main() { int n; printf("Entrez la valeur de n : "); scanf("%d", &n); if (n < 0) { printf("La valeur de n doit être un entier positif ou nul.\n"); } else { long long resultat = suite(n); printf("U(%d) = %lld\n", n, resultat); } return 0; }
Cette version utilise long long
pour gérer des valeurs plus grandes, mais elle peut encore rencontrer des limitations pour des valeurs très grandes de .
La complexité temporelle d'un algorithme mesure comment le temps d'exécution de l'algorithme augmente en fonction de la taille de l'entrée. Dans le cas de la fonction suite
, la taille de l'entrée est représentée par le paramètre n
.
Analysons la fonction suite
pour comprendre pourquoi sa complexité temporelle est linéaire :
long long suite(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { long long U_n_2 = 0; // U(0) long long U_n_1 = 1; // U(1) long long U_n; for (int i = 2; i <= n; i++) { U_n = 3 * U_n_1 - U_n_2; U_n_2 = U_n_1; U_n_1 = U_n; } return U_n; } }
Cas de base :
n
est 0 ou 1, la fonction retourne immédiatement une valeur constante (0 ou 1). Ces cas de base ont une complexité temporelle constante .Boucle for
:
n
supérieures ou égales à 2, la fonction utilise une boucle for
qui itère de 2 à n
.n - 1
itérations (de i = 2
à i = n
).U_n
en utilisant l'expression 3 * U_n_1 - U_n_2
.U_n_2
et U_n_1
.Complexité totale :
for
effectue n - 1
itérations, et chaque itération a une complexité .La fonction suite
a une complexité temporelle linéaire parce que le temps d'exécution de la fonction augmente linéairement avec la valeur de n
. En d'autres termes, si n
double, le temps d'exécution double également (à une constante près). Cela est dû à la boucle for
qui effectue un nombre d'itérations proportionnel à n
, avec chaque itération ayant un coût constant.
Si on implémente une version récursive de la fonction suite
en reprenant directement la définition , la complexité temporelle sera exponentielle. Voici pourquoi :
long long suite_recursive(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { return 3 * suite_recursive(n - 1) - suite_recursive(n - 2); } }
Cas de base :
n
est 0 ou 1, la fonction retourne immédiatement une valeur constante (0 ou 1). Ces cas de base ont une complexité temporelle constante .Appels récursifs :
n
supérieures ou égales à 2, la fonction fait deux appels récursifs :
suite_recursive(n - 1)
suite_recursive(n - 2)
Arbre des appels récursifs :
n
, et le nombre total de nœuds dans un arbre binaire complet de hauteur n
est .Complexité totale :
n
.La version récursive de la fonction suite
a une complexité temporelle exponentielle parce que chaque appel récursif entraîne deux nouveaux appels récursifs, ce qui conduit à un arbre d'appels de taille exponentielle. Cela signifie que le temps d'exécution de la fonction augmente très rapidement avec la valeur de n
, rendant cette version inefficace pour des valeurs de n
même modérément grandes.
This Chat is read-only. Login to resume chatting.