Vous êtes sur la page 1sur 4

Quelques pistes sur l'algorithmique

Algorithme
1. Une définition
Un algorithme est la description d'une succession de directives permettant de passer, en un
nombre fini d'étapes, d'un état initial comportant un nombre fini de données à un état final qui
est son objectif.
L'exécution d'un algorithme ne doit pas laisser place à l'interprétation ou à l'imagination.
Exemple :
Trier en ordre croissant les listes T = [1,6,1,8,0,3,3,9,8,8,7,5] et U = [7,6,5,4,3,2,1].
Le tri de la liste U se fait sans problème mentalement, alors que ce sera le pire cas dans
certains algorithmes de tri.
Remarque :
Les problèmes algorithmiques ne sont pas spécifiques aux mathématiques.
Par exemple : trier une liste de noms par ordre alphabétique, trouver un mot dans un
dictionnaire, sortir d'un labyrinthe ...

2. Un exemple décliné dans différents langages


Pour un problème simple, l'algorithme de résolution ne dépend pas du langage utilisé.
Toutefois, selon le type de problème, certains langages seront mieux adaptés que d'autres.
Problème : on souhaite calculer le 51ème terme de la suite de Fibonacci définie par :

{ u 0 =0 et u 1 =1
∀ n ∈ℕ ,u n  2 = u n  u n  1
.

Algorithme : lire n (ici, n = 50)


U← 0 ; V← 1 ; W← 1 ; i← 2 (*)
tant que i < n faire (*)
U← V
V← W
W← U + V
i ← i+1
afficher W (*)
Voir en annexe l'implémentation dans différents langages.

3. Preuve d'un programme


En programmation impérative, il est important de prouver deux choses :
- la terminaison du programme
Il a été montré par Gödel qu'il ne pouvait pas exister de programme universel capable de
déterminer si un programme donné se termine pour tous ses arguments.
Toutefois, pour un programme donné, on peut prouver qu'il se termine en un nombre fini
d'étapes.
Dans l'exemple ci-dessus, la boucle est décrite n – 2 fois.
- la validité du programme
Il existe une théorie entière consacrée à la preuve formelle de programmes. On s'intéresse ici
seulement aux boucles (for et while) dans un programme impératif. On utilise un invariant de
boucle pour prouver ce type de programme.
Exemple :
Dans l'algorithme ci-dessus, la propriété (V = ui-1 et W = ui ) est toujours vérifiée au niveau des
(*). Elle est clairement vérifiée au début ; si elle est vérifiée à l'étape i, elle l'est aussi à l'étape i
+ 1. Elle est donc vérifiée en sortie de boucle. Comme dans ce cas, i = n, l'algorithme affiche
bien un. On dit que la propriété (V = ui-1 et W = ui ) est un invariant de boucle.

Bilan : Pour prouver un programme en utilisant un invariant de boucle, il faut :


- Définir une pré-condition qui décrit l'état des variables avant d'entrer dans la boucle.
- Prouver que l'invariant de boucle est vrai à chaque passage dans la boucle.
- La condition de sortie de boucle, en conjonction avec l'invariant de boucle, permet de
prouver une post-condition, ce qui valide le programme.
On peut également se servir de l'invariant de boucle pour montrer la terminaison d'un
programme ou pour étudier la complexité d'un programme.
4. Complexité d'un programme
Lorsqu'on considère un problème, il peut être intéressant de trouver plusieurs algorithmes
pour le résoudre, afin d'utiliser le mieux adapté. L'analyse de la complexité d'un algorithme
consiste à évaluer son temps d'exécution et la place mémoire nécessaire. Les notions de
complexité les plus couramment utilisées sont, pour un ensemble de données Dn de taille n et
un coût C(d) pour une donnée d ∈ Dn :
- la complexité dans le pire des cas : Cmax(n) = max{C(d) ; d ∈ Dn }
- la complexité en moyenne : C moy n = ∑ p d C d  , où p(d) représente la probabilité
d ∈D n
d'apparition de la donnée d parmi toutes les données de taille n.
Dans un algorithme de contrôle d'une centrale nucléaire, c'est la complexité dans le pire des
cas qui est intéressante ; dans un algorithme de recherche de pages web, c'est la complexité
moyenne qui évaluera la surcharge moyenne du serveur.

Exemple 1:
Dans l'algorithme de calcul des termes de la suite de Fibonacci, pour évaluer le temps
d'exécution du programme, on s'intéresse à Tn, le nombre de fois où la boucle est exécutée
pour le calcul de un . Or on a Tn = n – 2 ; si on ne tient pas compte de la taille des opérandes
(qui devient ici rapidement très grande), le temps d'exécution est donc de la forme a + bn. La
complexité de cet algorithme est linéaire.

Exemple 2 :
Si on dispose d'un langage récursif, on peut proposer un autre algorithme de calcul des termes
de la suite de Fibonacci : définition de f(n)
si n < 2, f(n) ← n
sinon f(n) ← f(n-1) + f(n-2)
Si on note Tn le nombre d'appels récursifs pour calculer f(n), on a T0 = T1 = 0 et
∀ n 2, T n =2 T n −1T n −2 .
On peut démontrer par récurrence que :
→ Tn = 2un – 2, pour tout entier n > 0, où (un) est la suite de Fibonacci
→ ∀ n ∈ℕ ,u n =n −−1 n , où Ф désigne le nombre d'or.
Donc lorsque n est grand, Tn est de l'ordre de Фn. Cet algorithme, bien que très court dans son
écriture, a une complexité exponentielle.

Exemples d'algorithmes en arithmétique


1. Techniques opératoires
Exercice 1 :
1°) Déterminer le développement décimal de 3/7 en posant la division.
Repérer la succession d'opérations effectuées lors de cette division.
2°) a et b entiers naturels non nuls et premiers entre eux, à quelle condition le nombre a/b
est-il un nombre décimal ?
3°) Écrire un algorithme permettant d'obtenir les n premiers chiffres du développement décimal
de a/b.
4°) Le développement décimal d'un nombre rationnel est périodique.
Utiliser l'algorithme précédent pour déterminer la période du développement décimal de 1/7,
1/14, 1/17.
Peut-on dire que la période du développement de 1/n est égale à n – 1 pour tout entier n ?
En testant plusieurs exemples, conjecturer une propriété vérifiée par cette période.

Exercice 2 : multiplication russe


On considère l'algorithme suivant, où x et y sont deux nombres entiers :
a←x
b←y
m ← 0 (*)
tant que a > 0 faire (*)
si a est impair, m ← m + b
b←b×2
a ← E(a / 2)
afficher m (*)
1°) Exécuter cet algorithme pour x = 5 et y = 2, puis pour x = 45 et y = 19.
On remplira un tableau donnant pour chaque étape les valeurs prises par a, b et m.
A l'aide de ces deux exemples, conjecturer la nature du résultat m renvoyé par cet algorithme.
2°) Prouver que l'égalité x × y = a × b + m est toujours vérifiée au niveau des (*).
En déduire que le résultat conjecturé au 1°) est bien vérifié.

2. Bases de numération
Exercice 1 :
1°) Écrire un algorithme permettant d'obtenir l'écriture en base 2 d'un nombre n à partir de
son écriture décimale.
2°) Même exercice avec la base 60. Donner une application de ce calcul.
3°) Généraliser l'algorithme obtenu au 1°) à une base b, où 1< b < 10 et construire une feuille
de calcul permettant d'effectuer la conversion d'un nombre de la base 10 à la base b.

Exercice 2 :
Deux temps t1 et t2 sont donnés en heures, minutes et
secondes. Les valeurs sont rentrées dans un tableur.
Trouver les formules permettant d'exprimer sur la ligne
4 le temps t1 + t2 en heures, minutes et secondes.

3. Ensemble des diviseurs d'un nombre entier naturel


Si n est un entier naturel (n > 1) et D l'ensemble de ses diviseurs strictement supérieurs à 1, D
est une partie non vide de ℕ , qui admet donc un plus petit élément d. d s'appelle le diviseur
minimal de n. On démontre que d est un nombre premier.
1°) Écrire un algorithme permettant d'obtenir le diviseur minimal d'un entier naturel n > 1,
puis le programme correspondant sur calculatrice.
2°) Utiliser ce programme pour :
- décomposer en produit de facteurs premiers 6006 et 111333.
- déterminer si le nombre 211 – 1 est premier.
- déterminer si les nombres 27, 28 et 945 sont parfaits, déficients ou abondants.
Remarque : On peut aisément construire un algorithme de décomposition d'un entier naturel
en produit de facteurs premiers, utilisant l'algorithme élaboré au 1°).

4. Algorithme d'Euclide
Cet algorithme permet de déterminer le PGCD de deux entiers naturels a et b :
1. Déterminer le reste r de la division euclidienne de a par b.
2. Si r = 0, alors l'algorithme se termine et PGCD(a ; b) = r
3. Sinon, remplacer a par b, b par r et recommencer à partir de (1).
Remarques :
- L'étape 3 est basée sur le fait que PGCD(a ; b) = PGCD(b ; r).
- L'algorithme se termine après un nombre fini de pas puisque les restes obtenus forment une
suite strictement décroissante d'entiers naturels.
1°) Écrire un programme sur calculatrice correspondant à l'algorithme précédent.
2°) Utiliser ce programme pour :
- déterminer le PGCD de 1569872 et de 16436.
- déterminer les diviseurs communs de 33264 et 222222.

Quelques idées d'algorithmes dans les autres parties du programme


• Algorithme de calcul de la dérivée
• Algorithme de calcul de la solution de l'équation f(x)=k, pour f continue et strictement
monotone (dichotomie et balayage)
• Algorithme de construction de la section d'un polyèdre par un plan.
• Algorithme de tri d'une liste dans le but de déterminer médiane et quartiles d'une série
statistique.
ANNEXE
Programmation de la suite de Fibonacci

En Pascal-Kylix-Delphi "Borland" En C
program fibonacci; /* Suite de Fibonacci en C */
{$APPTYPE CONSOLE}
uses
SysUtils; float Fibo (int n)
var resultat: int64; {
/* un+2=un+1+un */
function Fibo(n:integer):int64; int i;
var un2,un1,un,i : int64; float un,un1,un2;
begin un=0;
un:=0; un1=1;
un1:=1; un2=1;
un2:=1; i=2;
i:=2; while (i<n)
while (i<n) do {
begin un=un1;
un:=un1; un1=un2;
un1:=un2; un2=un1+un;
un2:=un1+un; i++;
i:=i+1; }
end; return un2;
Fibo:=un2; }
end;
void main()
begin {
// corps du programme float resultat=Fibo(50);
resultat:=Fibo(50); printf("fibo(50)=%E \n",resultat);
writeln('Fibo(50)='+inttostr(resultat)); }
end.
En Perl Calculatrice TI 89
#!/usr/bin/perl -w Fibo()
sub Fibo{ Prgm
# un+2=un+1+un Prompt n
my $un=0; 0→u
my $un1=1; 1→v
my $un2=1; 1→w
my $n=$_[0]; 2→i
my $i=2; While i<n
while ($i<$n) { v→u
$un=$un1; w→v
$un1=$un2; v+u→w
$un2=$un1+$un; i+1→i
$i=$i+1; Endwhile
} Disp w
return $un2; Endprgm
}
my $resultat=&Fibo(50);
print"Fibo(50)=$resultat \n";