Séance no 1 : Autour de l`algorithme d`Euclide 1 Rappels sur l

publicité
Univ. Lille 1 - IREM de Lille.
2010-2011
Stage Algorithmique
o
Séance n 1 : Autour de l'algorithme d'Euclide
Éric Wegrzynowski. (Eric.Wegrzynowski (a) univ-lille1.fr)
1
Rappels sur l'algorithme d'Euclide
Pour déterminer le pgcd de deux nombres entiers, on peut procéder par soustractions successives comme Euclide l'a montré dans ses Éléments. Le principe consiste à retrancher le plus petit
des deux nombres au plus grand et de remplacer le plus grand par la diérence ainsi calculée.
On itère le calcul tant que les deux nombres sont diérents. Le pgcd est égal au nombre obtenu
en n de calcul.
Ainsi pour calculer le pgcd de a = 33 et b = 18, on a calcule successivement
33 − 18 = 15
18 − 15 = 3
15 − 3 = 12
12 − 3 = 9
9−3=6
6−3=3
Après 6 soustractions, les deux nombres obtenus sont égaux à 3, et nous pouvons conclure que
pgcd(33, 18) = 3.
Une autre façon de procéder, qui demande moins d'étapes de calcul, consiste à eectuer des
divisions successives dans lesquelles, à partir de la deuxième division, le dividende est le diviseur
de la division qui précède, et le diviseur est le reste de la division qui précède.
33 = 18 × 1 + 15
18 = 15 × 1 + 3
15 = 3 × 5 + 0
Une version formalisée de cet algorithme par divisions successives est présenté dans la gure
1.1.
La gure 1 montre une trace des calculs eectués lorsque a = 33 et b = 18 (la colonne q donne
les quotients successifs).
2
L'algorithme programmé version 1
On peut trouver une réalisation dans le langage de programmation de Xcas de l'algorithme
d'Euclide 1.1 dans la gure 2. La fonction irem est une fonction prédénie en Xcas qui calcule
le reste dans la division euclidienne.
A faire 1 Recopiez le texte de ce programme à l'aide d'un éditeur de textes. Puis chargez-le dans
Xcas.
Testez votre programme avec les exemples de votre choix.
1
Algorithme 1.1 Algorithme d'Euclide pour le calcul du pgcd par divisions euclidiennes
Entrée : a et b deux entiers naturels non tous deux nuls.
Sortie : d = pgcd(a, b)
1: Poser a1 = a et b1 = b.
2: tant que b1 6= 0 faire
3:
Calculer le reste r de la division euclidienne de a1 par b1 .
4:
Donner à a1 la valeur de b1 .
5:
Donner à b1 la valeur de r.
6: n tant que
7: renvoyer a1
i
q
r
1
2
3
1
1
5
15
3
0
a1
33
18
15
3
b1
18
15
3
0
pgcd(33,18) = 3
Figure 1 Calcul de pgcd(33, 18)
3
L'algorithme programmé version 2
Le style dans lequel l'algorithme d'Euclide a été décrit et programmé est le style impératif.
Le style de programmation impérative est celui utilisé par beaucoup de programmeurs, et dans
beaucoup de langages de programmation. Dans ce style, la notion principale est celle de machine
à états modiables au cours du temps par des instructions. Dans le cas de notre programme,
l'état de la machine qui nous concerne est décrit par les 3 variables a1 , a2 et r dont les valeurs
évoluent au cours du temps.
On peut programmer dans un style fonctionnel dans lequel la notion d'états d'une machine
n'est plus nécessaire. Dans ce style de programmation,
plus de variables dont les valeurs changent, les variables sont simplement des noms qui
désignent une valeur immuable ;
plus d'aectations ;
plus de boucles pour et tant que.
Mais alors comment programmer des calculs qui nécessitent une itération ?
C'est l'expression récursive très proche de la notion de récurrence.
Par exemple, pour notre calcul de pgcd, on peut entièrement décrire une méthode de calcul
qui s'énonce en deux énoncés dont on perçoit immédiatement la validité. D'une part, le pgcd
d'un entier positif et de 0 est cet entier :
pgcd(a, 0) = a,
et d'autre part, le pgcd de a ≥ 0 et b > 0 est égal au pgcd de b et de a (mod b) :
pgcd(a, b) = pgcd(b, a (mod b)).
Ces deux énoncés permettent une expression récursive du calcul du pgcd, en utilisant toujours
le second si le nombre b n'est pas nul, et le premier dans le cas contraire. Ainsi, le calcul de
2
euclide1 (a,b) := {
local a1, b1, r;
a1 := a ;
b1 := b ;
tantque b1 <> 0 faire
r := irem(a1,b1) ;
a1 := b1 ;
b1 := r ;
ftantque ;
retourne a1 ;
}
Figure 2 Euclide programmé en Xcas
pgcd(33, 18) se déploie en cette série d'égalités
pgcd(33, 18) = pgcd(18, 15)
= pgcd(15, 3)
= pgcd(3, 0)
=3
En observant les calculs eectués, on se convainc aisément que cette façon de procéder revient
au même que la précédente.
Ces deux énoncés donnent l'algorithme 1.2 qui s'exprime par une simple expression conditionnelle.
Algorithme 1.2 Algorithme d'Euclide version récursive.
Entrée : a et b deux entiers naturels non tous deux nuls.
Sortie : d = pgcd(a, b)
1: si b = 0 alors
2:
renvoyer a
3: sinon
4:
renvoyer pgcd(b, a (mod b))
5: n si
La récursivité est un moyen élégant de présenter des algorithmes, qui sont en général beaucoup
plus lisibles que leurs homologues itératifs. Leur preuve de validité est aussi plus simple que pour
les algorithmes itératifs.
Beucoup de langages permettent l'expression récursive. Xcas est de ceux-là.
A faire 2 Programmez une fonction que vous nommerez euclide2 qui suit cet algorithme récursif.
Testez-le sur les exemples de votre choix.
Remarque : par défaut Xcas limite à 50 la profondeur des appels récursifs. Il est possible de
modier cette limitation dans le menu de conguration.
3
4
Analyse de l'algorithme d'Euclide
On s'intéresse maintenant au nombre de divisions nécessaires pour le calcul du pgcd avec
l'algorithme d'Euclide.
On note cout(a, b) le nombre de divisions eectuées dans le calcul de pgcd(a, b) par l'algorithme d'Euclide. Cela dénit une fonction de N × N dans N.
On l'a déjà remarqué, qu'on utilise sa version itérative ou bien sa version récursive, le coût
est le même.
Pour a = 33 et b = 18, on a
cout(33, 18) = 3.
4.1
On compte
A faire 3 Il est assez facile de modier l'une ou l'autre des deux versions de programme de calcul de
pgcd que vous avez écrits pour obtenir un programme qui calcule la fonction cout. Faîtes-le !
4.2
Recherche de records
A faire 4 Pour les couples (a, b) de nombres compris entre 1 et 100 avec a ≥ b, quel est le plus grand
nombre de divisions dans le calcul du pgcd de ces couples ?
Quels sont le(s) couple(s) pour lesquels ce nombre est atteint ?
A faire 5 Recherchez le couple d'entiers (a, b), a ≥ b, les plus petits possibles pour lequel le nombre de
divisions dans le calcul du pgcd est 11.
A faire 6 Recommencez le travail précédent pour des nombres de divisions compris entre 1 et 11.
4.3
Les lapins à notre secours !
Les nombres successifs 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, . . . ne vous rappellent rien ?
Ce sont les termes successifs de la célèbre suite de nombres de Fibonacci, Leonardo de son
prénom, qu'il a conçue au XIIIème siècle pour étudier la croissance d'une population de lapins.
Cette suite se dénit par ses deux premiers termes
F0 = 1
F1 = 1
et pour tout entier n ≥ 0 la relation de récurrence
Fn+1 = Fn+1 + Fn
A faire 7 Quel est le pgcd de deux termes consécutifs de la suite de Fibonacci ? Combien de divisions
pour le calcul de ce pgcd ?
Vers 1845, Gabriel Lamé a montré que pour tout couple d'entiers (a, b), tels que a ≥ b, le
nombre de divisions dans le calcul du pgcd de ces deux nombres par l'algorithme d'Euclide est
borné supérieurement par cinq fois le nombre de chires nécessaires pour écrire b en base 10.
Pour cela il a montré que pour tout couple de nombres (a, b) tels que a ≤ Fn+1 , et b ≤ Fn , on a
cout(a, b) ≤ n.
A faire 8 Concevez en Xcas une fonction récursive qui calcule le terme Fn pour un entier n passé en
paramètre.
4
Le calcul récursif des nombres de Fibonacci n'est pas très ecace. La raison en est relativement
simple si on suit ce calcul pour un petit indice, comme par exemple 4.
F5 = F4 + F3
= (F3 + F2 ) + (F2 + F1 )
= ((F2 + F1 ) + (F1 + F0 )) + ((F1 + F0 ) + F1 )
= (((F1 + F0 ) + F1 ) + (F1 + F0 )) + ((F1 + F0 ) + F1 )
= (((1 + 1) + 1) + (1 + 1)) + ((1 + 1) + 1)
=8
Lors du calcul de F5 , F3 est calculé deux fois, et F2 est calculé trois fois. Pour des indices plus
grands, les répétitions de calcul sont encore bien plus nombreuses.
A faire 9 Concevez en Xcas un algorithme itératif pour calculer le terme Fn .
A faire 10 Calculez les valeurs approchées du rapport de deux termes consécutifs de la suite de
pour des indices de plus en plus grands. (Utilisez la fonction evalf.)
Fibonacci FFn+1
n
A faire 11 Utilisez la fonction rsolve de Xcas pour obtenir une expression de Fn en fonction de n.
Le nombre de Fibonacci Fn est équivalent à
√
5+ 5 n
Fn ∼
Φ ,
10
où le nombre Φ =
√
(1+ 5)
2
est le célèbre nombre d'or.
A faire 12 Vériez que le nombre de divisions dans le calcul du pgcd de deux nombres a ≥ b ne dépasse
jamais 5 fois le nombre de chires de b en base 10.
5
Calcul de PGCD binaire
Dans son ouvrage The Art of Computer Programming, vol 3, Donald Knuth décrit une méthode de calcul du pgcd de deux nombres entiers, qui s'avère particulièrement bien adaptée aux
nombres écrits en base 2.
Cette méthode ne requiert que soustractions, multiplications et divisions par 2, ces deux
dernières opérations s'avérant n'être que de simples décalages dans le cas de la base 2.
Une présentation récursive telle qu'on peut la trouver dans le Cours d'Algèbre de Michel
Demazure, édition Cassini, est donnée dans l'algorithme 1.3.
A faire 13 Programmez en Xcas une fonction de calcul du pgcd de deux entiers qui suit cet algorithme.
5
Algorithme 1.3 Calcul de PGCD binaire
Entrée : a et b deux entiers naturels non nuls.
Sortie : d = pgcd(a, b).
si a = b alors
renvoyer a
sinon si a et b pairs alors
renvoyer 2pgcd(a/2, b/2) {Dans la suite, quitte à échanger u et v, on suppose v impair.}
sinon si u pair alors
renvoyer pgcd(u/2, v)
sinon si u > v alors
renvoyer pgcd((u − v)/2, v)
sinon
renvoyer pgcd((v − u)/2, u)
n si
6
Téléchargement