Vous êtes sur la page 1sur 42

Variations sur le schéma de Horner

(Programmation avec Maple)


Préparation à la nouvelle épreuve d’informatique
de l’École Polytechnique.

Jean-Michel Ferrard
Avant-propos
Ce document vise à la préparation à la nouvelle épreuve d’informatique de l’École Polytechnique.
Les caractéristiques de cette épreuve peuvent être consultées à l’adresse :
http ://www.enseignement.polytechnique.fr/informatique/concours/
Parmi les langages de programmation possibles, on a choisi Maple, dont on n’a utilisé que les fonc-
tionnalités de base, conformément aux demandes des concepteurs de l’épreuve.
Le présent document est consacré à l’algorithme de Horner et à ses variations dans des domaines
parfois inattendus. Voici un bref résumé des différentes thèmes abordés :
– Partie I : Évaluation d’un polynôme
C’est l’aspect le plus classique de l’algorithme de Horner. On voit deux méthodes, dont l’une est
récursive. On s’intéresse aussi à l’évaluation en un point de C d’un polynôme à coefficients réels,
toujours dans le souci de diminuer le nombre d’opérations à effectuer.
– Partie II : Division synthétique
L’algorithme de Horner (évaluation d’un poynôme P en un point α) cache en fait une méthode de
division de P par x − α. Dans cette partie, on voit également comment former (à moindre frais)
la division euclidienne de P par X 2 + αX + β.
– Partie III : Translatés d’un polynôme, dérivées successives
On voit ici comment calculer les coefficients du polynôme P (X + α) à partir de ceux de P (X).
On constate qu’on y arrive par deux algorithmes de Horner imbriqués. Développer P (X + α) c’est
aussi exprimer le polynôme P dans la base des (X − α)k . On en déduit en particulier une méthode
pour calculer simultanément les dérivées successives de P en α.
– Partie IV : Règle des signes de Descartes
Elle donne une indication sur les racines positives ou négatives d’un polynôme. L’utilisation de
translations permet alors de localiser des racines de P sur n’importe quel intervalle.
– Partie V : Méthode de Newton de résolution de P (x) = 0
Elle permet d’approcher une racine réelle du polynôme P . On se sert d’algorithmes de Horner en
parallèle pour calculer simultanément les valeurs de P (x) et de P 0 (x) (voire de P 00 (x).)
– Partie VI : Forme de Newton du polynôme interpolateur
Il s’agit d’écrire ici le polynôme interpolateur d’une famille de points sous une forme qui permet
(entre autres) facilement l’ajout d’un point supplémentaire. L’évaluation de ce polynôme s’effectue
par une forme particulière de l’algorithme de Horner.
– Partie VII : Autour du théorème chinois
Dans cette partie, on voit comment trouver la solution d’un système de congruences. On voit que
des calculs “à la Horner” permettent d’obtenir cette solution en minimisant le nombre d’opérations,
et surtout en limitant la taille des calculs intermédiaires.
– Partie VIII : Algorithmes “compte-gouttes”
Dans cette partie, on étudie et on met en œuvre des méthodes qui permettent d’obtenir rapidement
un grand nombre de décimales des nombres e et π. Là encore, ce sont des calculs “à la Horner”.
Algorithmique avec Maple
Variations sur le schéma de Horner

Table des matières

Énoncé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
I. Évaluation d’un polynôme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
II. Division synthétique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
III. Translatés d’un polynôme, dérivées successives . . . . . . . . . . . . . . . . . . 4
IV. Règle des signes de Descartes . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
V. Méthode de Newton de résolution de P (x) = 0 . . . . . . . . . . . . . . . . . . 6
VI. Forme de Newton du polynôme interpolateur . . . . . . . . . . . . . . . . . . . 6
VII. Autour du théorème chinois . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
VIII. Algorithmes “compte-gouttes” . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Corrigé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
I. Évaluation d’un polynôme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
II. Division synthétique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
III. Translatés d’un polynôme, dérivées successives . . . . . . . . . . . . . . . . . . 16
IV. Règle des signes de Descartes . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
V. Méthode de Newton de résolution de P (x) = 0 . . . . . . . . . . . . . . . . . . 20
VI. Forme du Newton du polynôme interpolateur. . . . . . . . . . . . . . . . . . . 23
VII. Autour du théorème chinois . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
VIII. Algorithmes “compte-gouttes” . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Page 2 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

Énoncé
Un polynôme P est représenté par un tableau unidimensionnel T de réels, indicé à partir de 1.
Le type d’un tel tableau est array(numeric).
Un tel tableau, lu dans l’ordre des indices croissants, représente un unique polynôme représenté
lui-même dans le sens des puissances décroissantes.
Par exemple, le tableau T = [3, 0, −5, 2, 1] représente le polynôme P = 3X 4 − 5X 2 + 2X + 1.
On utilisera la fonction size suivante pour calculer la taille d’un tableau unidimensionnel T : c’est
un majorant strict du degré du polynôme P associé à T .
> size:=proc(T::array(numeric))
> RETURN(op(2,op(2,eval(T))));
> end:
Par exemple, les tableaux T et U sont de tailles respectives 5 et 7. Evidemment, ils représentent deux
polynômes qui sont de degrés respectifs 4 et 2.
> T:=array([3,0,-5,2,1]):
> U:=array([0,0,0,0,2,4,1]):
> size(T), size(U);
5, 7
Par commodité, on nommera de la même manière un polynôme P et le tableau qui le représente.

I. Évaluation d’un polynôme


Dans cette première partie, on voit comment évaluer un polynôme P à coefficient réels avec l’algo-
rithme de Horner, c’est-à-dire en se basant sur la deuxième expression ci-dessous de P (t).
n
ak tk = ((· · · (((an t + an−1 ) t + an−2 ) t + an−3 + · · ·) t + a1 ) t + a0
P
P (t) =
k=0

1. Écrire une fonction evalh évaluant P en le réel t, avec la syntaxe evalh(P, t).
Cette valeur sera calculée par un algorithme de Horner itératif.
Indiquer le nombre d’additions et de multiplications nécessitées par cet algorithme. [ S ]
2. Écrire une version récursive de la fonction evalh, avec la même syntaxe d’appel. [ S ]
3. Dans cette question, on cherche à évaluer P (z), où z = x + iy est un nombre complexe.
On suppose que les seules opérations possibles sont l’addition et le produit de nombres réels.
Écrire une fonction evalhc, déduite de la version itérative de evalh pour que evalhc(P, x, y)
renvoie le tableau [x0 , y 0 ] donnant la partie réelle et la partie imaginaire de P (x + iy).
Combien cette méthode nécessite-t-elle d’opérations arithmétiques sur les réels ? [ S ]
4. Écrire une autre version de evalc, plus écononome en opérations sur les réels.
On pensera à la division euclidienne de P par X 2 − 2Re (z)X + |z|2 . [ S ]

Page 3 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

II. Division synthétique


Soit P un polynôme et t un réel. On vient de voir comment calculer y = P (t).
Dans les questions 1 et 2, on voit comment effectuer la division de P par X − t.
On sait que P (t) est le reste dans cette division : il faut donc calculer le quotient Q.

1. Écrire une fonction quo1 donnant le quotient Q de P par le monôme X − t.


La syntaxe d’appel sera quo1(P, t) et le résultat sera le tableau associé à Q. [ S ]

2. Écrire une procédure Quo1 calculant à la fois le quotient Q et le reste R = P (t).


Cette procédure modifie le tableau P en y plaçant les coefficients de Q puis R = P (t)
La syntaxe d’appel sera Quo1(P, n, t), où n est la taille du tableau P .
L’argument n signifie en fait qu’on utilise les n premiers coefficients du tableau P .
On verra dans la question suivante quelle utilité il y a à utiliser cette syntaxe. [ S ]

3. Dans cette question, on divise P par X 2 + αX + β.


n−2
On note P = (X 2 + αX + β) bk+2 X k + b1 X + b0 cette division.
P
k=0
Écrire une procédure Quo2 calculant à la fois le quotient Q et le reste R = b1 X + b0 .
On utilisera la syntaxe Quo2(P, α, β). z
Q
}|
R
{ z }| {
Cette procédure transforme le tableau [an , an−1 , . . . , a0 ] en [bn , bn−1 , . . . , b2 , b1 , b0 ] [ S ]

III. Translatés d’un polynôme, dérivées successives


n
ak X k , et t un réel.
P
On considère un polynôme P =
k=0
On sait qu’il est possible d’écrire P sur la base des polynômes (X − t)k , k ∈ N.
n n
bk (X − t)k ⇔ P (X + t) = bk X k .
P P
Plus précisément : P (X) =
k=0 k=0
On se propose ici de voir comment passer du tableau [an , . . . , a1 , a0 ] au tableau [bn , . . . , b1 , b0 ].
On résout ainsi deux problèmes équivalents :
– Trouver les coefficients de Q(X) = P (X + t) (translaté de P ) sur la base des X k .
– Trouver les coefficients du polynôme P sur la base des (X − t)k .
1. Avec les notations ci-dessus, écrire une procédure Translat modifiant P = [an , a . . . , a1 , a0 ]
pour y placer les coefficients bn , . . . , b1 , b0 .
La syntaxe est Translat(P, t), et on fera appel à la procédure Quo1. [ S ]

2. Écrire une fonction translat, renvoyant le tableau Q = [bn , . . . , b1 , b0 ].


On utilisera la syntaxe Translat(P, t), et on ne fera pas appel à la procédure Quo1. [ S ]

Page 4 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

3. Vérifier que translat nécessite 12 (n2 − n) additions et autant de multiplications.


Écrire une autre version de cette fonction nécessitant moins de 3n multiplications.
Indication : en utilisant des homothéties de rapport t ou 1/t, se ramener à t = 1.
Cette économie se fait au prix d’un tableau supplémentaire contenant [tn , tn−1 , . . . , t, 1]. [ S ]

4. Écrire une fonction derivs prenant en argument un polynôme P (représenté par le tableau
[an , . . . , a1 , a0 ]) et un réel t, et renvoyant le tableau [P (n) (t), . . . , P 0 (t), P (t)] des dérivées suc-
cessives de P au poit t (par ordre décroissant de l’ordre de dérivation.) [ S ]

IV. Règle des signes de Descartes


n
ak X k , représenté par le tableau P = [an , an−1 , . . . , a1 , a0 ].
P
Considérons le polynôme P =
k=0

On appelle changement de signe dans P tout couple (i, j), avec i < j et :
– Les coefficients ai et aj sont non nuls et de signe contraire.
– Pour tout k tel que i < k < j on a ak = 0.
On observe donc un changement de signe quand deux coefficients non nuls consécutifs de P (ordonné
suivant les puissances croissantes ou décroissantes) sont de signes contraires.
Par exemple, le polynôme P = X 8 − 3X 5 + 2X 4 + X 2 − X − 1 présente 3 changements de signe.
Notons s le nombre de changements de signe de P .
La règle de Descartes affirme que le nombre r de racines réelles strictement positives de P est
inférieur ou égal à s, et plus précisément que la différence s − r est un entier pair.
Par exemple, cette règle permet d’affirmer que le polynôme P = X 8 − 3X 5 + 2X 4 + X 2 − X − 1
possède ou bien trois ou bien une seule racine(s) réelle(s) strictement positive(s).
Appliquée à P (−X), cette règle donne une indication sur les racines réelles strictement négatives.
Avec notre exemple, P (−X) = X 8 + 3X 5 + 2X 4 + X 2 + X − 1 présente un seul changement de signe.
Le polynôme P possède donc exactement une racine réelle strictement négative.
1. Écrire une fonction varsign donnant le nombre de changements de polynôme P . [ S ]

2. Écrire une fonction rootsup donnant un majorant du nombre de racines de P strictement


supérieures à un réel donné a. On utilisera la syntaxe rootsup(P, a). [ S ]

3. Écrire une fonction rootinf donnant un majorant du nombre de racines de P strictement


inférieures à un réel donné a. On utilisera la syntaxe rootinf(P, a). [ S ]

Page 5 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

V. Méthode de Newton de résolution de P (x) = 0


Soit f : I ⊂ R → R, de classe C k (k ≥ 1). La méthode de Newton consiste à chercher une
f (xn )
solution x de f (x) = 0 en formant une suite définie par x0 ∈ I et par ∀ n ∈ N, xn+1 = xn − 0 .
f (xn )
Dans la suite de cette question f est un polynôme P à coefficients réels.
La convergence n’est pas assurée (sauf vers la plus grande racine réelle α de P si x0 > α.)
La vitesse de convergence est quadratique vers une racine simple, et linéaire vers une racine multiple.
1. Écrire une fonction newton donnant xn+1 connaissant P et xn .
On utilisera évidemment une schéma de Horner pour évaluer P (xn ) et P 0 (xn ).
On fera en sorte que ces deux schémas soient menés en parallèle. [ S ]
P
2. On peut songer à appliquer la méthode de Newton à la fraction rationnelle f = .
P0
Ses zéros sont ceux de P et ils sont tous simples.
Cela assure une vitesse de convergence au moins quadratique pour toutes les racines de P .
P (xn )P 0 (xn )
Dans ce cas on doit donc utiliser la relation : xn+1 = xn − 02 .
P (xn ) − P (xn )P 00 (xn )
Écrire alors une fonction newton2 donnant xn+1 connaissant P et xn . On fera en sorte que les
calculs de P (xn ), P 0 (xn ), P 00 (xn ) soient menés en parallèle. [ S ]

VI. Forme de Newton du polynôme interpolateur


Soit F une famille de n points Ak (xk , yk ) du plan, avec 1 ≤ k ≤ n, d’abscisses xk distinctes.
On sait qu’il existe un polynôme unique P , de degré ≤ n−1, tel que P (xk ) = yk pour tout k.
Il y a plusieurs façons d’écrire ce polynôme interpolateur, dont la forme de Newton.
Elle consiste à écrire P dans la base H1 , H2 , . . . , Hn de Rn−1 [X] définie par :

H1 = 1, H2 = X −x1 , H3 = (X −x1 )(X −x2 ), ..., Hn = (X −x1 )(X −x2 ) · · · (X −xn−1 )

Le problème est double :


– Calculer les coordonnées de P sur la base H1 , H2 , . . . , Hn .
– Connaissant ces coordonnées, évaluer P en un point quelconque.
C’est dans ce deuxième problème qu’intervient un schéma de Horner.
1. Pour 1 ≤ i ≤ j ≤ n, on définit récursivement les coefficients di,j de la manière suivante :
di+1,j − di,j−1
Pour tout i de {1, . . . , n}, di,i = yi . Si i < j, on pose di,j = .
xj − xi
Écrire une fonction dij calculant le coefficient d’indice i, j.
La syntaxe sera dij(X, Y, i, j) où X, Y sont les tableaux des abscisses et ordonnées.
La fonction dij utilisera bien sûr la définition récursive des coefficients di,j . [ S ]

Page 6 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

2. Avec les notations ci-dessus, on montre que P = d1,1 H1 + d1,2 H2 + · · · + d1,n Hn .


Écrire une fonction pnewton formant le tableau [d1,1 , d1,2 , . . . , d1,n ] à partir des tableaux X, Y
(tous les deux indicés de 1 à n) des abscisses et ordonnées.
La fonction pnewton s’appuiera essentiellement sur la fonction dij qui calcule les coefficients
di,j (et en particulier les d1,k ) de façon récursive. [ S ]

3. La méthode précédente a un défaut : des calculs intermédiaires sont effectués plusieurs fois.
D’autre part, on voit bien qu’il suffit ici de calculer les seuls coefficients d1,k .
Écrire une procédure PNewton calculant le tableau [d1,1 , d1,2 , . . . , d1,n ].
On n’utilisera pas la fonction récursive dij. Au contraire les coefficients d1,k seront calculés par
une méthode itérative. Voici une indication sur les premières étapes du calcul :
– On part du tableau Y = [d1,1 , d2,2 , . . . , dn,n ].
– La première étape transforme ce tableau en [d1,1 , d1,2 , . . . , dj,j+1 , . . . , dn−1,n ].
– L’étape suivante conduit à [d1,1 , d1,2 , d1,3 , . . . , dj,j+2 , . . . , dn−2,n ], etc.
A la n−1-ième étape, on aboutit donc au tableau [d1,1 , d1,2 , d1,3 , . . . , , d1,n ].
On utilisera la syntaxe PNewton(X, Y ). Les calculs seront faits dans le tableau Y . [ S ]

4. Avec la forme du Newton, il est très facile d’ajouter un nouveau point A0 (x0 , y0 ).
Écrire une fonction newpoint passant du polynôme interpolateur P de (x1 , y1 ), . . . , (xn , yn )
(écrit sous sa forme de Newton) à celui des n + 1 points (x0 , y0 ), (x1 , y1 ), . . . , (xn , yn ).
Avec la syntaxe newpoint(X, P, x0 , y0 ), où X est la liste des n abscisses initiales, le résultat
sera le tableau de la forme de Newton du polynôme interpolant A0 , . . . , An . [ S ]
5. Écrire une fonction evalnewton calculant la valeur en un point x quelconque du polynôme
d’interpolation P des n points Ak (xk , yk ). La syntaxe sera evalnewton(X, P, x), où X est la
liste des n absicsses et où P est le tableau de taille n représentant la forme de Newton du
polynôme interpolateur. [ S ]

VII. Autour du théorème chinois


Dans cette partie (réservée aux élèves de MP*), on s’intéresse au “théorème chinois”.
– Soient m, n dans N∗ , avec m ∧ n = 1. On sait qu’il existe une infinité de couples (u, v) de Z2 tel
que um + vn = 1. On dit que u et v sont des coefficients de Bezout de m et n.
Il existe en particulier un couple (u, v) unique tel que |u| ≤ n2 et |v| ≤ m
2.
Il est obtenu par l’algorithme d’Euclide (divisions successives) appliqué au couple (m, n).
– On se donne r entiers strictement positifs n1 , n2 , . . . , nr premiers entre eux deux à deux.
r
Q r
Q
Soit n = nk . On considère l’application ϕ de Z/nZ dans Z/nk Z définie par :
k=1 k=1
∀ x ∈ Z/nZ, ϕ(x) = (x mod n1 , x mod n2 , . . . , x mod nr )

Page 7 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

Cette application est un morphisme d’anneaux, injectif car son noyau est réduit à 0.
x mod n1 = a1

Il est donc bijectif pour des raisons de cardinal. 
x mod n2 = a2

En particulier, pour tous entiers a1 , . . . , ar : ∃ ! x ∈ [ 0, . . . , n−1 ], (S)
 ..
 .
Ce résultat est communément appelé théorème chinois. x mod nr = ar
1. Calcul des coefficients de Bezout.
(a) Écrire une fonction récursive bezout recevant les entiers positifs m, n et renvoyant dans un
tableau [u, v, u ∧ v] les coefficients u, v tels que um + vn = u ∧ v. Pour cela, et si m = nq + r
est la division de m par n, on notera comment passer d’un couple de coefficients de Bezout
de (n, r) à un couple de coefficients de Bezout de (m, n). [ S ]

(b) Écrire une version itérative de la fonction bezout.


Indication : considérer les équations (Eδ ) : am + bn = δ, d’inconnue (a, b) dans Z2 .
Le triplet (1, 0) est solution de (Em ), et (0, 1) est solution de (En ).
Soit α = qβ + r la division euclidienne d’un entier α par un entier β.
On suppose que (a1 , b1 ) est solution de (Eα ) et que (a2 , b2 ) est solution de (Eβ ).
On remarque alors que (a1 − qa2 , b1 − qb2 ) est solution de (Er ). [ S ]

2. Solution d’un système de congruences


(a) Pour tous i, j de {1, . . . , r} (avec i 6= j) on note ui,j et uj,i tels que ui,j ni + uj,i nj = 1.
Q Pr 
Pour tout j de {1, . . . , r}, on note Mj = ui,j ni , et on pose x = aj Mj mod n.
i6=j j=1
Montrer que l’entier x est l’unique solution du système (S).
Écrire une fonction chinese calculant x (syntaxe chinese([a1 , . . . , ar ], [n1 , . . . , nr ]). [ S ]

(b) Dans cette question, on calcule la solution x, au moyen de deux schémas de Horner.
On pose b1 = a1 , puis b2 = (a2 − b1 )u1,2 mod n2 , etc, et finalement
br = [([(ar − b1 )u1,r − b2 ]u2,r − b3 ) · · · − br−1 ] ur−1,r mod nr
Pr  k−1
Q 
Montrer que la solution x du système (S) s’écrit x = bk ni .
k=1 i=1
Vérifier que x peut être calculé en utilisant un schéma de Horner.
En déduire une nouvelle version de la fonction chinese.
Remarque : Cette deuxième méthode a l’avantage de minimiser le nombre de “modulos”
à calculer, et de ne produire aucun calcul intermédiaire qui sortirait de [0, . . . , n−1]. [ S ]

VIII. Algorithmes “compte-gouttes”


Dans cette section, on étudie des algorithmes permettant de déterminer une à une les décimales de
e et de π. Connus sous le nom d’algorithmes “compte-gouttes”, leur particularité est de n’utiliser
que l’arithmétique des “petits” entiers, et de donner une à une les décimales successives du nombre
considéré sans réutiliser les décimales déjà calculées. Ces algorithmes opèrent une conversion d’un

Page 8 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

système de numération “à base variable” vers la numération décimale (ou en base 10p si on veut p
chiffres à la fois.) Cette conversion s’effectue en utilisant des calculs “à la Horner”.
1. Une numération à base variable, adaptée au nombre e
On note B l’ensemble des suites d’entiers (bn )n≥1 telles que
– Pour tout n ≥ 2, bn ∈ {0, . . . , n − 1}, mais b1 est quelconque dans Z.
– Pour tout n ≥ 1, il existe m ≥ n tel que bm < n − 1.

P bn
On va voir que tout x s’écrit d’une manière unique x = n! , où la suite (bn ) est dans B.
n=1
On pourra alors noter x = (b1 , b2 , . . . , bn , . . .)b .
On peut comparer ce développement avec la représentation décimale.
Notons en effet D l’ensemble des suites d’entiers (dn )n≥1 telles que
– Pour tout n ≥ 2, dn ∈ {0, . . . , 9}, mais d1 est quelconque dans Z.
– Pour tout n ≥ 1, il existe m ≥ n tel que dm < 9.

P dn
On sait qu’on a une unique écriture x = 10n−1 , où la suite (dn )n≥1 est dans D.
n=1
Plus précisément, on a d1 = [x] et, pour tout n ≥ 2, dn = [10n−1 x] mod 10.
Ce qui distingue les deux types de numération, c’est que l’écriture décimale utilise la base
fixe d = 10 (et on décompose sur des puissances successives de 1/10n ) alors que l’écriture
x = (b1 , b2 , . . . , bn , . . .)b utilise une “base” variable 1, 2, 3, . . ., et une décomposition sur les 1/n!

P 1
Evidemment pour e = exp(1), on a : e = 2 + k! c’est-à-dire e = (2, 1, 1, . . . , 1, . . .)b .
k=2
Un algorithme de conversion de la base variable b à la base 10 (ou mieux à une base 10p ),
permettra donc de récupérer les chiffres décimaux du nombre e.
P bk
(a) Soit (bn )n≥1 une suite de B. Montrer que k! converge. On note x sa somme.
n k≥1 ∞
P bk P bk
Pour tout n ≥ 0, on pose xn = k! (par convention, x 0 = 0) et r n = k! .
k=1 k=n+1
1
Montrer que pour tout n de N∗ , on a : 0 ≤ rn < n!
En déduire que b1 = [x] et, pour tout n ≥ 2, bn = [n!x] − n!xn−1 = [n!x] mod n. [ S ]

(b) Soit x un nombre réel.



P bk
Montrer qu’il existe une suite unique (bn )n≥1 de B telle que x = k! .
n k=1
P bk 1
∀ n ≥ 1, xn = k! est alors une valeur approchée de x par défaut à n! près. [ S ]
k=1
n
P bk
(c) Écrire une fonction todec calculant xn = k! à partir du tableau B = [b1 , . . . , bn ].
k=1
On utilisera la syntaxe todec(B, n), sans vérifier si le tableau B est correct. [ S ]
n
P bk
(d) Écrire une fonction tovar renvoyant B = [b1 , . . . , bn ] à partir de xn = k! .
k=1
On utilisera la syntaxe tovar(xn , n). [ S ]

Page 9 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

2. Le calcul des décimales du nombre e


+∞
P bk
(a) Soit x un nombre réel. On sait que x s’écrit de manière unique x = k! avec (bn ) ∈ B.
n k=1
P bk
Pour tout n ≥ 2, on note xn = k! = (b1 , b2 , . . . , bn )b .
k=1 n
10m bk
Soit m dans N∗ . On se propose de trouver la partie entière de 10m xn =
P
k! .
k=1
Il est bien sûr possible d’écrire 10m xn = (10m b1 , 10m b2 , . . . , 10m bn )b .
Mais dans cette écriture, les 10m bk (pour k ≥ 2) ne sont en général pas dans {0, . . . , k−1}.
On doit donc convertir cette écriture vers la base B.
Notons 10m xn = (r1 , r2 , . . . , rn )b l’écriture de 10m xn dans cette base.
Imaginer un algorithme permettant de passer de (b1 , b2 , . . . , bn )b à (r1 , r2 , . . . , rn )b .
Indication : procéder par divisions successives avec report de retenue, de bn à b2 . [ S ]

(b) Écrire une procédure goutte :


– Prenant en argument le tableau X = [b1 , b2 , . . . , bn ] et l’entier m ≥ 1.
– Plaçant le tableau [r1 , r2 , . . . , rn ] dans la variable X.
Remarque : cette méthode donne en particulier la partie entière r1 de 10m xn . [ S ]
1
(c) Montrer l’inégalité n! < 10−(n+1) pour n ≥ 27. En déduire une fonction chiffres e
donnant les n premières décimales de e, avec la syntaxe chiffres e(n, m), le paramètre
m indiquant que les décimales sont obtenues par blocs de m chiffres successifs.
Le résultat sera donné sous la forme d’une chaı̂ne de caractères. [ S ]
3. Le calcul des décimales de π
+∞
P (k!)2 2k
On admet l’égalité suivante : π2 = (2k+1)! .
k=0
Le terme général de cette série s’écrit uk = 3 · 51··72···
· 3 ··· k
(2k+1) .
   
π 1 1·2 1·2·3 1 2 3 4
Ainsi 2 = 1 + 3 + 3 · 5 + 3 · 5 · 7 + · · · = 1 + 3 1 + 5 1 + 7 1 + 9 (1 + · · ·) .

On peut donc considérer le système de numération P à base variable 1, 31 , 13 ·· 25 , 13 ·· 52 ·· 73 , . . .


Dans ce système de numération, on a visiblement : π = (2, 2, 2, 2, . . .)P .
Plus généralement, on considère des développements de la forme suivante :
+∞ +∞    
pk 3 · 51··72···
· 3 ··· k 1 2 3 4
P P
x= pk uk = p0 + (2k+1) = p 0 + 3 p 1 + 5 p 2 + 7 p 3 + 9 (p 4 + · · ·)
k=0 k=1

On notera x = (p0 , p1 , p2 , . . .)P le réel représenté par ce développement infini, avec p0 ∈ Z.


On dit qu’un tel développement est régulier si pk ∈ {0, . . . , 2k}, pour tout k ≥ 1, et si pour
tout entier n ≥ 1, il existe m ≥ n tel que pm < 2k.
On notera alors xn = (p0 , p1 , p2 , . . . , pn−1 , 0, 0, . . .)P , pour tout n ≥ 1.

Page 10 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Énoncé

(a) Montrer qu’un développement régulier (0, p1 , p2 , p3 , . . .)P converge vers un réel de [0, 2[.
La partie entière de (p0 , p1 , p2 , p3 , . . .)P est donc égale à p0 ou à p0 + 1.
Montrer qu’il n’y a pas unicité de la représentation d’un réel x dans le système P. [ S ]
n−1
P
(b) Écrire une fonction todec2 calculant xn = pk uk à partir de X = [p0 , . . . , pn−1 ].
k=0
On utilisera la syntaxe todec2(X), sans vérifier si le tableau X est correct. [ S ]
(c) Soit xn = (p0 , p1 , p2 , . . . , pn−1 , 0, . . .)P la somme d’un développement régulier fini.
Soit m un entier strictement positif. Imaginer un algorithme permettant d’obtenir un
développement régulier de 10m xn . [ S ]
(d) Ecrire une fonction goutte2, comme celle de la question (2b), réalisant la conversion
étudiée à la question précédente. Vérifier qu’une application répétée de cette fonction
20
P
donne par exemple les 30 premières décimales de π21 = (2, 2, 2, . . . , 2)P = 2 uk . [ S ]
+∞ m−1 k=0
P P
(e) On sait que π = 2 uk . Pour tout m ≥ 1, on pose πm = 2 uk .
k=0 k=0
Vérifier que 0 < π − πm < 4um (observer que uk < 21 uk−1 pour tout k ≥ 1.)
Montrer en outre que um est strictement inférieur à 23 2−m , pour m ≥ 1.
En déduire que si m ≥ 10 −n
3 n, alors 0 < π − πm < 5 · 10 . [ S ]
(f) Déduire de ce qui précède une fonction chiffres pi donnant les n premières décimales
de π, avec la syntaxe chiffres pi(n, m), le paramètre m indiquant que les décimales sont
calculées par groupes de m chiffres consécutifs.
Le résultat sera donné sous la forme d’une chaı̂ne de caractères. [ S ]

Page 11 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Corrigé
I. Évaluation d’un polynôme
Deux versions de l’algorithme de Horner :
n
ak X k est représenté par le tableau P = [an , an−1 , . . . , a1 , a0 ].
P
1. Le polynôme P =
k=0
Le calcul de y = P (t) s’effectue en posant d’abord y = 0, puis successivement :
y ← yt + an = an , y ← yt + an−1 = an t + an−1 ,
y ← yt + an−2 = an t2 + an−1 t + an−2 , . . . , y ← yt + a0 = P (t)
Voici donc la fonction itérative evalh qui calcule y = P (t) :
> evalh:=proc(P::array(numeric),t::numeric)
> local y,k; y:=0; # initialisation
> for k to size (P) do y:=y*t+P[k] od; # boucle de calcul de y = P (t)
> RETURN(y) # renvoie la valeur calculée
> end:
On calcule ici la valeur du polynôme P = 3X 4 − 5X 2 + 2X + 1 au point t = 100 :
> P:=array([3,0,-5,2,1]): evalh(P,100);
299950201
Il est clair que l’algorithme précédent nécessite n additions et n multiplications. [ Q ]
n n−1
ak X k , et le quotient Q = ak+1 X k dans la division de P par X.
P P
2. Soit P =
k=0 k=0
Pour tout réel t, on a donc y = P (t) = tQ(t) + a0 . 
P = [an , an−1 , . . . , a2 , a1 , a0 ]
Les polynômes P et Q sont représentés par les tableaux
Q = [an , an−1 , . . . , a2 , a1 ]
On voit que pour calculer y = P (t), il suffit de calculer z = Q(t) et de poser y = tz + a0 .
Pour évaluer Q(t), on peut encore utiliser le tableau initial P , à condition de se limiter aux
n + 1 premiers coefficients, c’est-à-dire à an , an−1 , . . . , a2 , a1 .
Il en découle la fonction evalhr, version récursive de l’algorithme de Horner.
Tout le travail est effectué par la fonction locale h, qui utilise toujours le tableau P représentant
le polynôme initial, mais qui reçoit en argument la longueur du sous-tableau de P représentant
l’un polynômes quotients successifs. Pour calculer y = P (t), il suffit donc d’un appel initial à
cette fonction locale, en lui transmettant la taille du tableau P .
> evalhr:=proc(P::array(numeric),t::numeric)
> local h;
> h:=proc(m)
> if m=1 then P[1] else h(m-1)*t+P[m] fi;
> end:
> RETURN(h(size(P))); # appel initial, sur tout la longueur de P
> end:

Page 12 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On reprend l’exemple qui a servi à illustrer la version récursive de l’algorithme :


> P:=array([3,0,-5,2,1]): evalhr(P,100);
299950201
Remarque : si on s’en tient aux directives des concepteurs de la nouvelle épreuve d’informatique
de l’X, on doit éviter d’emboı̂ter les fonctions. Il faut donc “sortir” la fonction locale h.
Une première solution est de réécrire la fonction evalhr de la manière suivante, en modifiant la
syntaxe d’appel et en confiant donc à l’utilisateur le soin de préciser la taille du tableau initial :
> evalhr2:=proc(P::array(numeric),n::integer,t::numeric)
> if n<=1 then P[1] else evalhr2(P,n-1,t)*t+P[n] fi;
> end:
On reprend encore le même exemple (remarquer que les syntaxes d’appel sont différentes.)
> P:=array([3,0,-5,2,1]): evalhr2(P,5,100);
299950201
[Q]

3. Voici la fonction evalhc, directement calquée sur la version itérative de evalh.


On utilise les variables locales u et v pour désigner la partie réelle et la partie imaginaire du
nombre complexe qui finira par être égal à P (x + iy).
> evalhc:=proc(P::array(numeric),x::numeric,y::numeric)
> local u,v,k,t; u:=0; v:=0;
> for k to size(P) do
> t:=u*x-v*y+P[k]; v:=u*y+v*x; u:=t;
> od;
> RETURN(array([u,v]))
> end:
On calcule ici P (−11 + 8i), avec P = 3X 4 − 5X 2 + 2X + 1.
> P:=array([3,0,-5,2,1]): evalhc(P,-11,8);
[−83487, −59296]
On vérifie tout de même que le résultat est correct :
> p:=x->evalc(3*x^4-5*x^2+2*x+1): p(-11+8*I);
−83487 − 59296I
On voit que l’algorithme précédent nécessite 3n additions et 4n multiplications de réels. [ Q ]

4. Posons r = 2Re (z) = 2x et m = |z|2 = x2 + y 2 .


n
ak X k par B = (X − z)(X − z̄) = X 2 − rX + m.
P
Considérons la division du polynôme P =
k=0
n−2
Cette division euclidienne s’écrit P = (X 2 − rX + m) bk+2 X k + b1 X + b0 .
P
k=0
Avec ces notations, on a bien sûr P (z) = b1 z + b0 = (b1 x + b0 ) + ib1 y.

Page 13 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Par identification, on trouve tout d’abord : bn = an , bn−1 = an−1 + rbn .


Ensuite, pour tout k de {1, . . . , n−2} : bk = ak + rbk+1 − mbk+2 .
Par identification de termes constants, on trouve enfin b0 = a0 − mb2 .
Posons plutôt b00 = a0 + rb1 − mb2 pour rester dans la continuité des formules donnant les bk .
On a alors P (z) = (b1 x + b0 ) + ib1 y = (b1 x + b00 − rb1 ) + ib1 y = (b00 − b1 x) + ib1 y. Voici donc la
deuxième version de la fonction evalhc.
> evalhc2:=proc(P::array(numeric),x::numeric,y::numeric)
> local r,m,b,c,k,t;
> r:=x+x; m:=x*x+y*y; b:=0; c:=0;
> for k to size(P) do t:=P[k]+r*b-m*c; c:=b; b:=t; od;
> RETURN(array([b-c*x,c*y]))
> end:
On reprend l’exemple précédent, pour vérifier que les résultat est correct :
> P:=array([3,0,-5,2,1]): evalhc2(P,-11,8);
[−83487, −59296]
On note que cet algorithme nécessite 2n + 3 additions et 2n + 4 multiplications de réels, au lieu
des 3n additions et 4n multiplications de la première version. [ Q ]

II. Division synthétique


n
ak X k , représenté par le tableau P = [an , an−1 , . . . , a1 , a0 ].
P
Considérons le polynôme P =
n−1 k=0
bk X k le quotient de P par X − t, représenté par Q = [bn−1 , bn−2 , . . . , b1 , b0 ].
P
Soit Q =
k=0
n−1 n−1
bk X k + P (t) = bn−1 X n + (bk−1 − bk t)X k + P (t) − b0 t.
P P
On a P = (X − t)Q + P (t) = (X − t)
k=0 k=1
Par identification, on trouve bn−1 = an et : ∀ k ∈ {1, .., n−1}, bk−1 = bk t + ak .
Ainsi le calcul de Q = [bn−1 , . . . , b1 , b0 ] s’effectue en posant virtuellement bn = 0, puis :

bn−1 ← bn t + an = an , bn−2 ← bn−1 t + an−1 = an t + an−1 ,


bn−3 ← bn−2 t + an−2 = an t2 + an−1 t + an−2 , . . . , b 0 ← b 1 t + a1

Ce sont les mêmes calculs que dans la question 1.a (algorithme de Horner itératif), mais il faut
conserver les résultats intermédiaires plutôt que de se contenter du résultat final.
1. Pour remplir le tableau Q, on écrira donc successivement :
Q[1] ← P [1], Q[2] ← Q[1] t+P [2], Q[3] ← Q[2] t+P [3], Q[n−1] ← Q[n−2] t+P [n−1]
On en déduit la forme itérative pour la fonction quo1 :
> quo1:=proc(P::array(numeric),t::numeric)
> local n,Q,k; n:=size (P); # taille du tableau P

Page 14 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> if n=1 then RETURN(array([0])) fi; # si P constant, le quotient est nul


> Q:=array(1..n-1); Q[1]:=P[1]; # initialisations
> for k from 2 to n-1 do # boucle de calcul du quotient
> Q[k]:=Q[k-1]*t+P[k];
> od; RETURN(eval(Q)); # renvoie le quotient
> end:
Ici, on considère le polynôme P = X 8 − 6X 7 + 9X 6 + X 5 − X 4 + X 3 − 2X 2 + 1.
On voit que le quotient de P par X − 3 est Q = X 7 − 3X 6 + X 4 + 2X 3 + 7X 2 + 19X + 57.
> P:=array([1,-6,9,1,-1,1,-2,0,1]); quo1(P,3);
P := [1, −6, 9, 1, −1, 1, −2, 0, 1]
[1, −3, 0, 1, 2, 7, 19, 57]
[Q]
2. La procédure Quo1 effectue le travail à la fois de evalh et quo1, et est plus simple à écrire.
> Quo1:=proc(P::array(numeric),n::integer,t::numeric)
> local k;
> for k from 2 to n do # boucle de calcul des coefficients de Q
> P[k]:=P[k-1]*t+P[k]; # puis de la valeur P (t)
> od; # cette dernière est obtenue pour k = size(P )
> RETURN(); # on ne renvoie aucune résultat
> end:
On divise à nouveau P = X 8 − 6X 7 + 9X 6 + X 5 − X 4 + X 3 − 2X 2 + 1 par X − 3.
Une première méthode donne le quotient Q et le reste R (utilisation de quo1 et evalh.)
La deuxième méthode (procédure Quo1) place les deux résultats dans le tableau P .
> P:=array([1,-6,9,1,-1,1,-2,0,1]): quo1(P,3), evalh(P,3);
> Quo1(P,9,3); eval(P);
[1, −3, 0, 1, 2, 7, 19, 57], 172
[1, −3, 0, 1, 2, 7, 19, 57, 172]
Remarque : si P est constant, donc si le tableau initial se réduit à P = [a0 ], ce tableau n’est
pas modifié Quo1 : le quotient est nul et n’apparaı̂t pas dans le résultat. [ Q ]

3. La méthode est celle qui a été vue dans la question I-4 : On procède toujours par identification,
et une simple boucle permet de calculer successivement tous les coefficients bk .
On a d’abord : bn = an , bn−1 = an−1 − αbn , puis : ∀ k ∈ {1, . . . , n−2} : bk = ak − αbk+1 − βbk+2 .
Par identification des termes constants, on trouve enfin b0 = a0 − βb2 .
Comme bn , bn−1 , . . . , b0 doivent aller dans les cellules P [1], P [2], . . . , P [n+1] de P , on écrira :
P [2] ← P [2] − αP [1], puis ∀k ∈ {3, . . . , n}, P [k] ← P [k] − αP [k−1] − βP [k−2]

Page 15 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Enfin, on calcule le terme constant en écrivant P [n + 1] ← P [n + 1] − βP [n − 1].


Voici la procédure Quo2. On a utilisé deux variables auxiliaires u, v initialisées à la valeur 0,
pour désigner les deux coefficients P [k − 1] et P [k − 2]. De cette manière, on peut simplifier
l’algorithme en évitant de tester les cas particuliers concernant le degré du polynôme P .
> Quo2:=proc(P::array(numeric),a::numeric,b::numeric)
> local m,u,v,k,t;
> m:=size (P); u:=0; v:=0; # initialisations
> for k to m do # boucle de calcul du quotient et du reste
> P[k]:=P[k]-a*u-b*v; v:=u; u:=P[k];
> od;
> P[m]:=u+a*v; # correction sur le terme constant
> RETURN()
> end:
On calcule ici le quotient et le reste de P = 3X 4 − 5X 2 + 2X + 1 par X 2 + 2X − 3.
On vérifie ensuite que le résultat est correct en utilisant les fonctions avancées de Maple.
> P:=array([3,0,-5,2,1]): Quo2(P,2,-3); eval(P);
> P:=3*x^4-5*x^2+2*x+1: Q:=quo(P,x^2+2*x-3,x,’R’): Q,R;
[3, −6, 16, −48, 49]
2
3x − 6x + 16, 49 − 48x
[Q]

III. Translatés d’un polynôme, dérivées successives


On effectue les divisions successives de P par (X −t). Ces divisions s’écrivent :

P = (X −t)Q1 + b0 , Q1 = (X −t)Q2 +b1 , Q2 = (X −t)Q3 +b2 , . . . , Qn−1 = (X −t)Qn +bn−1

Puisque deg P ≤ n, on a deg Qk ≤ n−k pour tout k. En particulier Qn est une constante bn .
n
Inversement ces égalités donnent P = b0 +b1 (X −t)+b2 (X −t)2 + · · · + bn (X −t)n = bk (X −t)k .
P
k=0

1. Pour calculer successivement b0 , b1 , . . . , bn , il suffit donc d’appeler n fois la procédure Quo1 de


division par (X − t) : la k-ième division fournit bk−1 , ainsi que le quotient Qk qui sert à la
division suivante. Tous les calculs se font dans le tableau P initial. C’est là qu’est utile le
deuxième paramètre dans la syntaxe d’appel de la procédure Quo1, qui permet d’effectuer la
division en n’utilisant que les k premiers coefficients du tableau.
> Translat:=proc(P::array(numeric),t::numeric)
> local k;
> for k from size (P) to 2 by -1 do
> Quo1 (P,k,t); # division par X −t, sur les k premiers coefficients de P
> od;
> RETURN(); # le résultat est dans le tableau P
> end:

Page 16 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On considère ici P = X 4 + 2X 3 − X 2 + 3X + 1.
(
P (X + 2) = X 4 + 10X 3 + 35X 2 + 55X + 35
On voit que
P (X) = (X −2)4 +10(X −2)3 +35(X −2)2 +55(X −2)+35
> P:=array([1,2,-1,3,1]): Translat(P,2); eval(P);
[1, 10, 35, 55, 35]
[Q]
2. Pour réécrire la procédure précédente, sous forme d’une fonction, il faut tout d’abord former
une copie Q indépendante du tableau initial P (avec l’instruction copy). Si ensuite on veut ne
plus utiliser la procédure Quo1, il suffit d’en recopier le contenu (à quelques détails près) dans
la fonction translat. Le résultat fait apparaı̂tre une double boucle finalement très simple.
> translat:=proc(P::array(numeric),t::numeric)
> local n,Q,j,k:
> n:=size (P); Q:=copy(P); # initialisations
> for k from n to 2 by -1 do # boucle de calcul du k-ième coefficient
> for j from 2 to k do # boucle de division par X −t
> Q[j]:=Q[j-1]*t+Q[j] # les calculs se font dans le tableau Q
> od;
> od;
> RETURN(eval(Q)); # renvoie le contenu du tableau Q
> end:
On reprend l’exemple qui a servi à illustrer la procédure précédente.
> P:=array([1,2,-1,3,1]): Q:=translat(P,2);
Q := [1, 10, 35, 55, 35]
[Q]

3. Pour former Q(x) = P (X + t), on peut procéder en trois étapes. On forme successivement
Q1 (X) = P (tX), puis Q2 (X) = Q1 (X + 1) = P (tX + t), puis Q(X) = Q2 (X/t) = P (X + t).
La translation se fait sans produit. Les deux autres étapes nécessitent n produits (ou divisions),
et il en faut à peu près autant pour créer le tableau contenant les puissances successives de t.
Voici la fonction (baptisée translat2), qui illustre cette idée. On remarquera le test initial
(sans lequel la fonction provoquerait une erreur dans la cas t = 0.)
> translat2:=proc(P::array(numeric),t::numeric)
> local n,Q,T,j,k:
> if t=0 then RETURN(eval(P)) fi; # ne change rien si t = 0
> n:=size(P); Q:=copy(P); T:=array(1..n); T[n]:=1; # initialisations
> for k from n-1 to 1 by -1 do # passe de X à tX
> T[k]:=t*T[k+1]; Q[k]:=Q[k]*T[k]
> od;
> for k from n to 1 by -1 do # passe de X à X + 1
> for j from 2 to k do Q[j]:=Q[j-1]+Q[j] od;
> Q[k]:=Q[k]/T[k]; # puis de X à X/t

Page 17 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> od;
> RETURN(eval(Q)); # renvoie Q(X) = P (X + t)
> end:
On reprend l’exemple utilisé précédemment.
> P:=array([1,2,-1,3,1]): Q:=translat2(P,2);
Q := [1, 10, 35, 55, 35]
[Q]
n
P (k) (t)
(X −t)k (formule de Taylor en t.)
P
4. On sait que P = k!
k=0 n
bk (X −t)k .
P
La question précédente a permis de calculer les bk tels que P =
k=0
On a bien entendu P (k) (t) = k! bk pour tout k de {0, 1, . . . , n}.
On appelle donc translat puis on transforme [bn , . . . , b1 , b0 ] en [n! bn , . . . , 1! b1 , 0! b0 ].
Pour rester “basique” on n’utilise pas la factorielle, mais un accumulateur local f .
> derivs:=proc(P::array(numeric),t::numeric)
> local n,Q,k,f:
> n:=size (P); f:=1; # degP = n−1, et 1 ! = 1
> Q:=translat (P,t); # calcule Q(x) = P (x+t)
> for k from 2 to n-1 do
> f:=f*k; # place k! dans la variable f
> Q[n-k]:=f*Q[n-k]: # calcule la dérivée k-ième de P en t
> od;
> RETURN(eval(Q)); # renvoie le tableau des dérivées successives
> end:
On considère à nouveau le polynôme P = X 4 + 2X 3 − X 2 + 3X + 1.
On voit que [p(4) (2), p(3) (2), p00 (2), p0 (2), p(2)] = [24, 60, 70, 55, 35].
> P:=array([1,2,-1,3,1]): Q:=derivs(P,1);
Q := [24, 60, 70, 55, 35]
[Q]

IV. Règle des signes de Descartes


1. On parcourt le tableau P . On utilise deux variables locales s et f :
– La variable s, initialisée à 0, mesure le nombre de changements de signe.
– La variable f , initialisée à 0, précise le signe courant.
> varsign:=proc(P::array(numeric))
> local k,s,f;
> f:=0; s:=0; # initialisations
> for k to size (P) do # sur toute la longueur du tableau
> if f*P[k]<0 then # s’il y a un changement de signe,

Page 18 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> s:=s+1; # on incrémente la variable s


> fi;
> if P[k]<>0 then # si on trouve un coefficient non nul
> f:=P[k] # il définit le signe courant
> fi;
> od; RETURN(s); # renvoie le nombre de changements de signe
> end:
On vérifie ici que P = X 9 −2X 8 +X 6 −X 5 +X 4 +X −1 présente 5 changements de signe.
> P:=array([1,-2,0,1,-1,1,0,0,1,-1]): varsign(P);
5
[Q]

2. Pour tout a de R, le nombre de racines réelles de P qui sont strictement supérieures à a est
égal au nombre de racines strictement positives de Q(X) = P (X + a).
Il suffit donc d’appeler la fonction varsign sur le tableau Q, lui même obtenu à partir du
tableau P grâce à la fonction translat.
> rootsup:=proc(P::array(numeric),a::numeric)
> RETURN(varsign (translat (P,a))) # sans commentaire...
> end:
Voici un polynôme dont les racines réelles sont 1, 3, 5 avec les multiplicités 1, 2, 1.
> P:=sort(expand((x-1)*(x-3)^2*(x-5)*(x^2+1)));
P := x6 − 12x5 + 51x4 − 96x3 + 95x2 − 84x + 45
On forme le tableau P associé à ce polynôme. On obtient ensuite un majorant s du nombre de
racines dans ]a, +∞[, avec successivement :
– a = 0 : on trouve s = 6 (il y a 4 racines > 0.) Il est normal que la différence soit paire.
– a = 1 : on trouve s = 3, ce qui confirme qu’il y a une ou trois racines > 1 (il y en a en fait
trois). On remarque que la racine égale à 1 n’est plus comptée.
– a = 4 : on trouve s = 1, ce qui prouve qu’il y a une racine > 4.
– a = 6 : on trouve s = 0 et c’est normal.
> P:=array([1,-12,51,-96,95,-84,45])
> rootsup(P,0),rootsup(P,1),rootsup(P,4),rootsup(P,6);
6, 3, 1, 0
[Q]
3. Le polynôme P possède autant de racines strictement inférieures à a que le polynôme Q(X) =
P (−X) en possède qui sont strictement supérieures à −a.
Il suffit donc de transformer le polynôme P en le polynôme Q (ou en −Q, peu importe) en
changeant un signe sur deux, puis d’appeler rootsup avec les arguments Q et −a.
> rootinf:=proc(P::array(numeric),a::numeric)

Page 19 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> local Q,k; Q:=copy(P); # copie indépendante de P


> for k to size (Q) by 2 do # boucle de passage de P à Q(X) = ± P (−X)
> Q[k]:=-Q[k]
> od;
> RETURN(rootsup (Q,-a)) # nombre de racines de P qui sont > a
> end:
Pour illustrer cette fonction, on reprend le polynôme P = (X − 1)(X − 3)2 (X − 5)(X 2 + 1).
On voit par exemple que rootinf(P, 1) renvoie la valeur 2, ce qui signifie que le nombre de
racines de P qui sont strictement inférieures 1 est soit égal à 2 soit égal à 0 (en fait, il est clair
qu’il n’y en a pas.) Rappelons que le nombre obtenu est toujours un majorant du nombre de
racines, et que l’erreur commise (s’il y en a une) est un entier pair.
Par exemple, le fait que rootinf(P, 4) renvoie la valeur 5 signifie que le nombre de racines
strictement inférieures à 4 est égal à 5, à 3, ou à 1 (ici on sait bien qu’il y en a trois.)
> P:=array([1,-12,51,-96,95,-84,45]):
> rootinf(P,0),rootinf(P,1),rootinf(P,4),rootinf(P,6);
0, 2, 5, 6
[Q]

V. Méthode de Newton de résolution de P (x) = 0


1. Il est intéressant de noter qu’on peut calculer simultanément y = P (x) et z = P 0 (x) par deux
algorithmes de Horner menés en parallèle.
Montrons comment se déroule le calcul quand par exemple P (x) = ax3 + bx2 + cx + d.
– On initialise les variables y et z à la valeur 0.
– On effectue z ← xz + y puis y ← xy + a. A ce stade, z = 0 et y = a.
– On effectue z ← xz + y puis y ← xy + b. A ce stade, z = a et y = ax + b.
– On effectue z ← xz + y puis y ← xy + c. A ce stade, z = 2ax + b et y = ax2 + bx + c.
– On effectue z ← xz + y puis y ← xy + d.
On a finalement obtenu z = 3ax2 + 2bx + c = P 0 (x) et y = ax3 + bx2 + cx + d = P (x).
Voici la fonction newton.
> newton:=proc(P::array,x)
> local n,y,z,k;
> n:=size(P); z:=0: y:=0; # initialisations
> for k to n do # double algorithme de Horner
> z:=x*z+y; y:=x*y+P[k];
> od;
> RETURN(x-y/z); # renvoie x − P (x)/P 0 (x)
> end:

Page 20 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On considère ici le polynôme P = X 3 + 3X 2 + X − 1, et on part de x0 = 1.


On calcule l’image x1 = x0 − P (x0 )/P 0 (x0 ) de x0 .
> P:=array([1,3,5,-1]): x:=newton(P,1.);
x := .4285714286
On calcule maintenant les termes suivants x2 , x3 , x4 , x5 , x6 .
On constate une convergence rapide vers x ≈ 0.1795090246 qui est effectivement racine de P .
> for k to 5 do x:=newton(P,x); od;
x := .2103374014
x := .1800440846
x := .1795091887
x := .1795090246
x := .1795090246
[Q]
2. On peut calculer y = P (x), z = P 0 (x) et t = 12 P 00 (x) par trois algorithmes de Horner parallèles.
Voici comment s’effectuerait le calcul dans le cas du polynôme P = aX 3 + bX 2 + cX + d :
– On initialise les variables y, z, t à la valeur 0.
– On effectue t ← xt + z, puis z ← xz + y et y ← xy + a.
A ce stade, t = 0, z = 0 et y = a.
– On effectue t ← xt + z, puis z ← xz + y et y ← xy + b.
A ce stade, t = 0, z = a et y = ax + b.
– On effectue t ← xt + z, puis z ← xz + y et y ← xy + c.
A ce stade, t = a, z = 2ax + b et y = ax2 + bx + c.
– On effectue t ← xt + z, puis z ← xz + y et y ← xy + d.
A ce stade, t = 3ax + b, z = 3ax2 + 2bx + c et y = ax3 + bx2 + cx + d.
On a bien obtenu y = P (x), z = P 0 (x) et t = 12 P 00 (x)
Voici donc la fonction newton2 :
> newton2:=proc(P::array,x)
> local n,y,z,t,k;
> n:=size(P);
> y:=0: z:=0; t:=0; # initialisations
> for k to n do # triple algorithme de Horner
> t:=x*t+z; # étape du calcul de P 00 (x)/2
> z:=x*z+y; # étape du calcul de P 0 (x)
> y:=x*y+P[k]; # étape du calcul de P (x)
> od;
> RETURN(evalf(x-y*z/(z^2-2*y*t)));
> end:

Page 21 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

A titre d’exemple, on forme le polynôme P := X 4 − 7X 3 + 13X + 3X − 18, qui possède les


racines −1 et 2 comme racines simples, et 3 comme racine double.
> P:=expand((X+1)*(X-2)*(X-3)^2);
P := X 4 − 7X 3 + 13X + 3X − 18
On convertit ce polynôme en la liste de ses coefficients.
> d:=degree(P,X):
> P:=array([seq(coeff(P,X,(d-k)),k=0..d)]);
P := [1, −7, 13, 3, −18]
On part de x0 = 4 et on calcule x1 , . . . , x15 obtenus par la méthode de Newton.
On observe une convergence finalement assez lente vers la racine 3 (la vitesse de convergence
n’est plus quadratique mais linéaire : la distance entre xn et 3 diminue à peu près de moitié à
chaque étape, ce qui est conforme avec le fait que x = 3 est une racine double.)
> x[0]:=4:
> for k to 15 do
x[k]:=newton(P,x[k-1]);
od:
> matrix(4,4,(i,j)->’x[4*i+j-5]’=x[4*i+j-5]);
 
x0 = 4, x1 = 3.629629630, x2 = 3.380010733, x3 = 3.219134317
 x = 3.120941970, x = 3.064354087, x = 3.033359459, x = 3.017011369 
 4 5 6 7 
 
 x8 = 3.008593728, x9 = 3.004320188, x10 = 3.002164732, x11 = 3.001085837 
x12 = 3.000545879, x13 = 3.000271374, x14 = 3.000133259, x15 = 3.000058237
En partant toujours de x0 = 4, on utilise ici la fonction newton2.
On constate que la convergence est beaucoup plus rapide.
Néanmoins, une certaine instabilité se manifeste au voisinage immédiat de la racine, en raison
de la formule utilisée pour passer de xn à xn+1 .
P (xn )P 0 (xn )
Rappelons que cette formule s’écrit xn+1 = xn − 02 .
P (xn ) − P (xn )P 00 (xn )
Dans cette égalité, le numérateur et le dénominateur sont proches de 0 quand xn est proche
d’une racine multiple de P .
> x[0]:=4:
> for k to 7 do
x[k]:=newton2(P,x[k-1]);
od:
> matrix(2,4,(i,j)->’x[4*i+j-5]’=x[4*i+j-5]);
" #
x0 = 4, x1 = 2.820960699, x2 = 2.972512076, x3 = 2.999505046
x4 = 3.000010762, x5 = 3.000022048, x6 = 3.000040505, x7 = 3.000100795
[Q]

Page 22 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

VI. Forme du Newton du polynôme interpolateur.


1. La fonction dij est une traduction fidèle de la définition récursive :
> dij:=proc(X,Y,i,j)
> if i=j then RETURN(Y[i]) else
> RETURN((dij (X,Y,i+1,j)-dij (X,Y,i,j-1))/(X[j]-X[i]));
> fi;
> end:
Une fois n’est pas coutume, on n’a pas “typé” les arguments de cette fonction.
Cela permet d’illustrer par les exemples suivants ce que sont les quantités di,j .
On dit souvent que les di,j sont les différences divisées associées aux points Ak (xk , yk ).
> dij(x,y,k,k); dij(x,y,k,k+1); dij(x,y,k,k+2);
yk+2 − yk+1 yk+1 − yk

yk+1 − yk xk+2 − xk+1 xk+1 − xk
yk , ,
xk+1 − xk xk+2 − xk
> dij(x,y,k,k+3);
yk+3 − yk+2 yk+2 − yk+1 yk+2 − yk+1 yk+1 − yk
− −
xk+3 − xk+2 xk+2 − xk+1 x − xk+1 xk+1 − xk
− k+2
xk+3 − xk+1 xk+2 − xk
xk+3 − xk
[Q]
2. Voici la fonction pnewton.
On forme les coefficients d1,k par des appels successifs à la fonction dij, et on les range dans
un tableau P de même longueur que X et Y .
> pnewton:=proc(X,Y)
> local n,P,k;
> n:=size (X); P:=array(1..n); # tableau P de même taille que X
> for k to n do # boucle de calcul des coefficients d[1, k]
> P[k]:=dij (X,Y,1,k)
> od;
> RETURN(eval(P)); # renvoie le contenu du tableau P
> end:
Là encore, on n’a pas “typé” les arguments de cette fonction, ce qui nous permet d’illustrer et
de vérifier son moyen au moyen d’un exemple symbolique.
> x:=array(1..3): y:=array(1..3): pnewton(x,y);
 y3 − y2 y2 − y1 

y2 − y1 x3 − x 2 x2 − x1 
 y1 , ,

x2 − x1 x3 − x1

Page 23 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Le polynôme d’interpolation associé aux points A1 (x1 , y1 ), A2 (x2 , y2 ), A3 (x3 , y3 ) est donc :
y3 − y2 y2 − y1

y2 − y1 x − x2 x2 − x1
P = y1 + (X − x1 ) + 3 (X − x1 )(X − x2 )
x2 − x1 x3 − x1
On constate effectivement que deg P ≤ 2 et que :
y2 − y1
P (x1 ) = y1 et P (x2 ) = y1 + (x2 − x1 ) = y2
x2 − x1
y3 − y2 y2 − y1

y2 − y1 x − x2 x2 − x1
P (x3 ) = y1 + (x3 − x1 ) + 3 (x3 − x1 )(x3 − x2 )
x2 − x1 x3 − x1
y2 − y1 y −y
3 2 y2 − y1 
= y1 + (x3 − x1 ) + − (x3 − x2 )
x2 − x1 x3 − x2 x2 − x1
y2 − y1
= y1 + ((x3 − x1 ) − (x3 − x2 )) + y3 − y2 = y3
x2 − x1
Voici maintenant un autre exemple d’utilisation de la fonction pnewton :
> X:=array([-1,0,1,2,3]): Y:=array([1,2,-3,-2,-7]): pnewton(X,Y);
[1, 1, −3, 2, −1]
Ce résultat signifie que le polynôme P de R4 [X] qui vérifie :
P (−1) = 1, P (0) = 2, P (1) = −3, P (2) = −2, P (3) = −7,
est donné par
P = 1 + (X +1) − 3(X +1)X + 2(X +1)X(X −1) − (X +1)X(X −1)(X −2)
[Q]
3. L’idée est de mener les calculs comme indiqué dans le tableau ci-dessous (avec n = 4).
Chaque colonne représente une étape de l’algorithme, et à chaque étape un coefficient nouvel-
lement calculé prend la place d’un coefficient calculé à l’étape précédente.
La première colonne représente bien sûr le vecteur Y initial.
On voit assez bien que les calculs doivent être menés dans une double boucle. L’indice de boucle
externe indique à quelle étape (dans quelle colonne) on se trouve, et l’indice de la boucle interne
parcourt la partie utile de cette colonne (selon les indices décroissants, pour qu’un coefficient
ne soit pas “recourvert” alors qu’il est encore utile.)

d1,1 = y1
d2,2 − d1,1
d2,2 = y2 d1,2 =
x2 − x1
d3,3 − d2,2 d2,3 − d1,2
d3,3 = y3 d2,3 = d1,3 =
x3 − x2 x3 − x1
d4,4 − d3,3 d3,4 − d2,3 d2,4 − d1,3
d4,4 = y4 d3,4 = d2,4 = d1,4 =
x4 − x3 x4 − x2 x4 − x1

Page 24 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Voici donc la procédure PNewton :


> PNewton:=proc(X,Y)
> local n,j,k;
> n:=size (X); # nombre de points
> for k to n-1 do # étape n◦ k
> for j from n to k+1 by -1 do # sur la partie utile du tableau
> Y[j]:=(Y[j]-Y[j-1])/(X[j]-X[j-k]); # calcul de d[j −k, j]
> od; od; RETURN(); # aucun résultat renvoyé
> end:
Pour illustrer cette procédure, on utilise le même exemple que précédemment :
> X:=array([-1,0,1,2,3]): Y:=array([1,2,-3,-2,-7]):
> PNewton(X,Y); eval(Y);
[1, 1, −3, 2, −1]
[Q]
4. Au départ, le tableau P contient donc [d1,1 , d1,2 , . . . , d1,n ].
On veut former le tableau Q = [d0,0 , d0,1 , d0,2 , . . . , d0,n ].
Cela revient bien à ajouter le point A0 (x0 , y0 ) “devant” les points A1 (x1 , y1 ), . . . , An (xn , yn ).
Le tableau X contient les abscisses initiales [x1 , x2 , . . . , xn ].
On contate que d0,0 , d0,1 , . . . , . . . , d0,n peuvent être calculés successivement en écrivant :

d1,1 − d0,0 P [1] − Q[1]


Q[1] = d0,0 = y0 , Q[2] = d0,1 = = ,...
x1 − x0 X[1] − x0
P [k] − Q[k] d1,n − d0,n−1 P [n] − Q[n]
Q[k+1] = d0,k = , . . . , Q[n+1] = d0,n = =
X[k] − x0 xn − x0 X[n] − x0

Voici donc la fonction newpoint, traduction fidèle de la remarque précédente.


> newpoint:=proc(X,P,x,y)
> local n,Q,k; n:=size (P); # il y a n points au départ
> Q:=array(1..n+1); Q[1]:=y; # initialise le tableau Q
> for k to n do # boucle de calcul des différences divisées
> Q[k+1]:=(P[k]-Q[k])/(X[k]-x)
> od;
> RETURN(eval(Q)); # forme de Newton du polynôme interpolant les n+1 points
> end:
On forme ici le polynôme interpolateur des quatre points (0, 2), (1, −3), (2, −2), 3, −7) :
> X:=array([0,1,2,3]): Y:=array([2,-3,-2,-7]): P:=pnewton(X,Y);
P := [2, −5, 3, −2]
On ajoute maintenant (−1, 1) devant les autres points. On retrouve ainsi le polynôme interpo-
lateur des cinq points (−1, 1), (0, 2), (1, −3), (2, −2), (3, −7).
>newpoint(X,P,-1,1);

Page 25 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

[1, 1, −3, 2, −1]


[Q]

5. Considérons par exemple les quatre points A1 (x1 , y1 ), . . . , A4 (x4 , y4 ), dans cet ordre.
Leur polynôme interpolateur sous sa forme de Newton est représenté par [d1,1 , d1,2 , d1,3 , d1,4 ].
Ainsi : P = d1,1 + d1,2 (X − x1 ) + d1,3 (X − x1 )(X − x2 ) + d1,4 (X − x1 )(X − x2 )(X − x3 ).
On peut réécrire le polynôme P sous la forme suivante (schéma de Horner) :
P = d1,1 + (X − x1 ) (d1,2 + (X − x2 ) (d1,3 + (X − x3 )d1,4 ))
Ainsi pour évaluer y = P (x), on pourra poser y = 0 puis effectuer successivement :
y ← d1,4 + (x − x4 )y = d1,4 y ← d1,3 + (x − x3 )y = d1,3 + (x − x3 )d1,4
y ← d1,2 + (x − x2 )y = d1,2 + (x − x2 ) (d1,3 + (x − x3 )d1,4 )
y ← d1,1 + (x − x1 )y = d1,1 + (x − x1 ) (d1,2 + (x − x2 ) (d1,3 + (x − x3 )d1,4 ))
La fonction evalnewton s’en déduit très simplement :
> evalnewton:=proc(X,P,x)
> local y,k; y:=0;
> for k from size(P) to 1 by -1 do y:=P[k]+(x-X[k])*y od;
> RETURN(y)
> end:
On reprend ici l’exemple des cinq points (−1, 1), (0, 2), (1, −3), (2, −2), (3, −7).
La procédure PNewton place la forme de Newton du polynôme interpolateur dans Y .
On évalue ensuite ce polynôme en x, ce qui illustre le mode d’évaluation.
Enfin, on vérifie que ce polynôme prend les valeurs 1, 2, −3, −2, −7 en −1, 0, 1, 2, 3.
> X:=array([-1,0,1,2,3]): Y:=array([1,2,-3,-2,-7]):
> PNewton(X,Y); eval(Y), P:=evalnewton(X,Y,x);
> seq(evalnewton(X,Y,X[k]),k=1..size(X));
[1, 1, −3, 2, −1], P := 1 + (x + 1)(1 + x(−3 + (x − 1)(4 − x)))
1, 2, −3, −2, −7
[Q]

VII. Autour du théorème chinois


1. Calcul des coefficients de Bezout.
(a) Soit m = nq + r la division euclidienne de m par n (avec 0 ≤ r < n.)
Soit (u0 , v 0 ) un couple vérifiant u0 n + v 0 r = n ∧ r.
Alors m ∧ n = n ∧ r = u0 n + v 0 (m − nq) = v 0 m + (u0 − qv 0 )n.
Autrement dit, le couple (u = v 0 , v = u0 − qv 0 ) vérifie um + vn = m ∧ n.
Voici donc une fonction récursive bezoutr utilisant cette idée, en notant que si n = 0 une
solution (u, v) de l’équation um + vn = m ∧ n = m est (1, 0).

Page 26 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Le résultat est donc un tableau [u, v, d] avec d = m ∧ n et um + vn = d.


> bezoutr:=proc(m::integer,n::integer)
> local C,q,r:
> if n=0 then C:=array([1,0,m]) else
> q:=floor(m/n); r:=m-q*n; # division de m par n
> C:=bezoutr (n,r); # identité de bezout pour n, r
> C:=array([C[2],C[1]-q*C[2],C[3]]) # identité de bezout pour m, n
> fi;
> RETURN(eval(C)); # renvoie [u, v, m ∧ n]
> end:
Avec m = 14938 et n = 9471, on constate que m ∧ n = 77 et que 26m − 41n = 77.
> bezout(14938,9471);
[26, −41, 77]
[Q]

(b) On commence par les égalités (Em ) (triplet [1, 0, m]) et (En ) (triplet [0, 1, m]).
On procède à des divisions successives sur les seconds membres, jusqu’à un reste nul.
A chaque pas, on trouve un nouveau triplet [u, v, δ], où δ est l’un des restes successifs.
A la fin, on aboutit à [u, v, m ∧ n]. NB : la solution récursive était plus simple !
> bezout2:=proc(m::integer,n::integer)
> local m,n,C1,C2,q,r,T,k:
> a:=m; b:=n; # recopie les deux entiers initiaux
> C1:=array([1,0,m]); # relation de Bezout 1.m + 0.n = m
> C2:=array([0,1,n]); # relation de Bezout 0.m + 1.n = n
> while b<>0 do # tant que le dernier reste est non nul
> q:=floor(a/b); r:=a-q*b; # division de a par b
> a:=b; b:=r; # actualise les valeurs de a et de b
> T:=copy(C1); C1:=copy(C2); # C1 = [u, v, a] tel que um + vn = a
> for k to 3 do
> C2[k]:=T[k]-q*C1[k]; # C2 = [u0 , v 0 , b] tel que u0 m + v 0 n = b
> od;
> od;
> RETURN(eval(C1)); # C1 = [u, v, m ∧ n], avec um + vn = m ∧ n
> end:
On reprend l’exemple utilisé précédemment.
> bezout2(14938,9471);
[26, −41, 77]
[Q]
2. Solution d’un système de congruences
(a) Pour tous indices i 6= j, les égalités ui,j ni + uj,i nj = 1 impliquent ui,j ni ≡ 1 (nj ).

Page 27 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

≡ 0 (ni ) si i 6= j

Q
Ainsi Mj = ui,j ni
i6=j ≡ 1 (nj )
Pr
Il en découle qu’on a effectivement x = aj Mj ≡ ai (ni ), pour tout i de {1, . . . , r}.
j=1

> chinese:=proc(A::array(integer),N::array(integer))
> local r,U,n,i,j,B,M,x;
> r:=size (N); # nombre de congruences
> U:=array(1..r,1..r); # prépare le tableau des u[i, j]
> n:=1; for i to r do n:=n*N[i] od; # calcule le produit n des n[k]
> for i to r do for j to i-1 do # pour 1 ≤ j < i ≤ r,
> B:=bezout (N[i],N[j]); # résout u[i, j]n[i] + u[j, i]n[j] = 1
> if B[3]<>1 then ERROR("gcd<>1") fi; # erreur si n[i] ∧ n[j] 6= 1
> U[i,j]:=B[1]; U[j,i]:=B[2]; # valeurs de u[i, j] et u[j, i]
> od; od;
> M:=array(1..r); # prépare le tableau des M [j]
> for j to r do M[j]:=1; # boucle de calcul du tableau M
> for i to r do # boucle pour calculer M [j]
> if i<>j then # × par U [i, j]M [i] si j 6= i
> M[j]:=(M[j]*U[i,j]*N[i]) mod n
> fi;
> od; od;
> x:=0; for j to r do # boucle de calcul de la solution x
> x:=(x+A[j]*M[j]) mod n;
> od;
> RETURN(x); # renvoie la solution x du système
> end:
Sur cet exemple, on met en place le système de congruences
x ≡ 11 (143) x ≡ 35 (223) x ≡ 42 (199) x ≡ 17 (301) x ≡ 22 (211)
La solution obtenue est x = 74269611713.
On constate que x est bien dans l’intervalle [0, . . . , n−1], avec ici n = 403035153521.
> A:=array([11,35,42,17,22]):
> N:=array([143,223,199,301,211]):
> n:=mul(N[k],k=1..5);
> chinese(A,N);

n := 403035153521
x := 74269611713
On vérifie que la solution obtenue est correcte :
> seq(x mod N[k],k=1..5);
11, 35, 42, 17, 22

Page 28 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Remarque : dans le listing ci-dessus (cf les lignes M[j] :=... et x :=...) on a effectué les
calculs intermédiaires “modulo n”. Sans cela, ces calculs conduisent à des entiers beaucoup
plus grands que n, et qui pourraient excéder les capacités arithmétiques du système (pas
celles de Maple, évidemment.) [ Q ]
 j−1
Q j−1
P j−1
Q 
(b) Après développement, on constate que bj = aj ui,j − (bk ui,j ) mod nj .
i=1 k=1 i=k
D’autre part, les égalités ui,j ni + uj,i nj = 1 donnent ui,j ni ≡ mod nj .
j−1
Q  j−1
P k−1
Q 
On en déduit bj n i = aj − (bk ni ) mod nj .
i=1 k=1 i=1
k−1
Q
Posons alors ck = bk ni .
i=1
 j−1
P 
Ce qui précède montre que cj ≡ aj − ck mod nj .
k=1
j
P
Ainsi ck ≡ ai mod ni .
k=1
r
P r
P k−1
Q
Conclusion : l’entier x solution du système (S) s’écrit x = ck = (bk ni ).
k=1 k=1 i=1
Enfin, l’entier x peut être calculé au moyen du schéma de Horner suivant :
x = b1 + (b2 + · · · + (br−2 + (br−1 + br nr−1 )nr−2 ) · · · n2 )n1
On peut maintenant écrire la nouvelle version de la fonction chinese.
Elle est beaucoup plus simple et efficace que la précédente.
On note en particulier qu’il n’est plus nécessaire d’utiliser de variable locale n pour y
placer le produit des nk , ni bien sur la tableau local M utilisé dans la première version.
La principale qualité de cette deuxième méthode est que tous les calculs intermédiaires se
font dans [0, . . . , n−1]. Les seuls calculs de congruences se font modulo les nk (et non plus
modulo n comme dans la première version).
C’est en particulier frappant dans le calcul final de la solution x, qui ne fait pas intervenir
aucune congruence...
> chinese:=proc(A::array(integer),N::array(integer))
> local r,U,i,j,B,x;
> r:=size(N);
> U:=array(1..r,1..r); # formation du tableau des u[i, j]
> for i to r do for j to i-1 do
> B:=bezout(N[i],N[j]);
> if B[3]<>1 then ERROR("pgcd<>1") fi;
> U[i,j]:=B[1];
> U[j,i]:=B[2];
> od; od;
> B:=copy(A); # formation de la suite des b[i]
> for i to r do

Page 29 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> for j to i-1 do


> B[i]:=(B[i]-B[j])*U[j,i] # c’est un premier schéma de Horner
> od;
> B[i]:= B[i] mod N[i] # seuls calculs de congruences
> od;
> x:=0; # formation de la solution du système
> for i from r to 1 by -1 do # c’est un second schéma de Horner
> x:=B[i]+x*N[i]; # et il n’y a pas de congruence
> od;
> RETURN(x); # renvoie la solution
> end:
On reprend ici l’exemple qui a servi à illustrer la première méthode.
> A:=array([11,35,42,17,22]):
> N:=array([143,223,199,301,211]):
> x:=chinese(A,N);
x := 74269611713
[Q]

VIII. Algorithmes “compte-gouttes”


1. Une numération à base variable, adaptée au nombre e
P bk bk 1
(a) La convergence de la série k! est immédiate car 0 ≤ k! < (k−1)! pour k ≥ 2.
∞ ∞  
P k−1 P 1 1 1
Pour tout n ≥ 1, on a 0 ≤ rn < k! c’est-à-dire 0 ≤ rn < (k−1)! − k! = n! .
k=n+1 k=n+1

L’inégalité stricte est justifiée par le fait qu’il existe k > n tel que bk < k − 1.
Les relations x = b1 + r1 et 0 ≤ r1 < 1 donnent alors b1 = [x].
Pour n ≥ 2, on peut écrire x = xn−1 + bn!n + rn , donc n!x = n!xn−1 + bn + n!rn .
 n−1
P bk 
Il est clair que n!xn−1 = n (n−1)! k! est un entier divisible par n.
k=1
Puisque 0 ≤ n!rn < 1, on en déduit [n!x] = n!xn−1 + bn .
On trouve donc finalement bn = [n!x] mod n, pour tout n ≥ 2. [ Q ]
(b) Supposons que le réel x s’écrive sous la forme indiquée.
D’après ce qui précède, on a nécessairement b1 = [x] et, ∀ n ≥ 2, bn = [n!x] mod n.
Il est d’abord évident que b1 est dans Z et que, pour tout n ≥ 2, bn est dans {0, . . . , n − 1}.
n ∞
P bk P bk
En reprenant les notations de l’énoncé, posons xn = k! et r n = k! .
k=1 k=n+1
Pour tout n ≥ 2, posons αn = [n!x] et soit αn = nqn + bn la division de αn par n.
Pour tout n ≥ 2, on a successivement :

Page 30 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

αn ≤ n!x < αn + 1 ⇒ nqn + bn ≤ n!x < nqn + bn + 1


⇒ qn ≤ qn + bnn ≤ (n−1)! x < qn + bnn+1 ≤ qn + 1
⇒ qn ≤ (n−1)! x < qn + 1 ⇒ qn = [(n−1)! x]
bn αn − nqn [n! x] [(n−1)! x]
Ainsi, pour tout n ≥ 2, = = − .
n! n n! (n−1)!
On en déduit, pour tout n ≥ 2 (mais le résultat final est valable aussi si n = 1) :
n n 
X bn X [k! x] [(k−1)! x]  [n! x] [n! x]
∀ n ≥ 2, xn = [x] + = [x] + − = [x] + − [x] =
k=2
n! k=2
k! (k−1)! n! n!

1
Pour tout n ≥ 1, on a n! x − 1 < [n! x] ≤ n! x donc x − n! < xn ≤ x.
1
Ainsi xn est-il une valeur approchée de x, par défaut, à n! près.

P bn
On a obtenu lim xn = x, ce qui prouve que x = n! .
n→∞ n=1
Il reste à prouver qu’on n’a jamais bn = n − 1 à partir d’un certain rang.
Supposons au contraire que bn = n − 1 pour tout n > p.
∞ ∞ ∞   p
P bn P n−1 P 1 1 1 P bn 1
Alors rp = n! = n! = (n−1)! − n! = p! , donc x = n! + p! .
n=p+1 n=p+1 n=p+1 n=1

On en déduit que p! x est un entier, et donc que (p+1)!x est un entier multiple de p+1.
Ainsi bp+1 = [(p+1)!x] mod (p+1) = (p+1)!x mod (p+1) = 0 : contradiction ! [ Q ]
n
P bk
(c) Pour calculer xn = k! à partir de B = [b1 , . . . , bn ], on utilise un schéma de Horner.
k=1
On peut en effet écrire :
  b  1  1  1 1 1
n
xn = ··· + bn−1 + bn−2 + bn−3 + ··· + b2 + b1
n n−1 n−2 n−3 3 2
Le réel xn peut donc être calculé en l’initialisant à la valeur 0 et en éxécutant les instruc-
xn
tions xn ← k+1 + B[k], de k = n à k = 1 (avec un “pas” de −1.)
Voici donc la fonction todec :
> todec:=proc(B::array(integer),n::integer)
> local x,k: x:=0;
> for k from n to 1 by -1 do x:=x/(k+1)+B[k]; od;
> RETURN(x);
> end:
A titre d’exemple, on forme le tableau des 16 premiers chiffres de la représentation de e :
> B:=array([2,1$15]);
B := [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Page 31 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On applique la fonction todec aux k premiers chiffres du tableau B, de k = 1 à k = 16,


en nommant x1 , . . . , x16 les résultats obtenus.
seq(evalf(x[k]=todec(B,k)),k=1..16);
x1 = 2., x2 = 2.500000000, x3 = 2.666666667, x4 = 2.708333333,
x5 = 2.716666667, x6 = 2.718055556, x7 = 2.718253968, x8 = 2.718278770,
x9 = 2.718281526, x10 = 2.718281801, x11 = 2.718281826, x12 = 2.718281828,
x13 = 2.718281828, x14 = 2.718281828, x15 = 2.718281828, x16 = 2.718281828
On voit bien comment la suite des xn converge vers le nombre e (du moins vers sa
représentation décimale e ≈ 2.718281828 calculée ici avec 10 chiffres significatifs.) [ Q ]

(d) Voici tovar. On remplit le tableau des bk , avec b1 = [x] et bk = [k!x] mod k si k ≥ 2.
On calcule k!x par accumulation progressive dans une variable locale y.
> tovar:=proc(x::numeric,n::integer)
> local B,y,k:
> B:=array(1..n); B[1]:=floor(x); y:=x;
> for k from 2 to n do
> y:=y*k; B[k]:=floor(y) mod k;
> end;
> RETURN(eval(B));
> end:
Sur cet exemple, on forme la décomposition de e (ou plus exactement de l’approximation
de e sur 10 chiffres significatifs : il n’est donc pas étonnant que les coefficients diffèrent de
1 au bout d’un certain temps.)
> e:=evalf(exp(1)); tovar(e,15);
e := 2.718281828
[2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 10]
[Q]

2. Le calcul des décimales du nombre e


n n
10m bk rk
(a) L’objectif est donc de passer de 10m xn = m
P P
k! à 10 x n = k! .
k=1 k=1
m
Dans cette dernière écriture, r1 = [10 xn ], et 0 ≤ rk < k pour k ≥ 2.
– La division de 10m bn par n s’écrit : 10m bn = qn n + rn , avec 0 ≤ rn < n.
n−2
P 10m bk 10m bn−1 10m bn n−2 P 10m bk 10m bn−1 qn n+rn
10m xn = k! + (n−1)! + n! = k! + (n−1)! + n!
k=1 k=1
n−2 m m
10 bk 10 bn−1 +qn
+ rn!n
P
= k! + (n−1)!
k=1
La première division s’est donc traduite par une retenue qn , reportée sur 10m bn−1 .

Page 32 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

– On divise maintenant b0n−1 = 10m bn−1 + qn par n−1.


Cette division s’écrit b0n−1 = qn−1 (n−1) + rn−1 , avec 0 ≤ rn−1 < n−1.
n−2 b0n−1 n−3
P 10m bk 10m bn−2 +qn−1
10m bk rn rn−1
Ainsi : 10m xn = + rn!n
P
k! + (n−1)! + n! = k! + (n−2)! + (n−1)!
k=1 k=1

– On continue ces divisions successives avec retenues. n


10m b2 +q3 rk
A l’avant-dernière étape, on a obtenu : 10m xn = 10m b1 +
P
2! + k!
k=3
Il reste à diviser b02 = 10m b2 + q3 par 2.
Cette division s’écrit b02 = 2q2 + r2 , avec r2 ∈ {0, 1}.
On obtient finalement, en posant r1 = 10m b1 + q2 :
n n
b0 rk rk
10m xn = 10m b1 + 2!2 + m
P P
k! = 10 b 1 + q 2 + k! = (r1 , r2 , . . . , rn )b .
k=3 k=2
La conversion est terminée, avec notamment r1 = [10m xn ]. [ Q ]

(b) Voici la procédure goutte, illustration de la méthode précédente :


> goutte:=proc(X::array(integer),m::integer)
> local q,k,b;
> q:=0; # initialise la retenue
> for k from size(X) to 2 by -1 do # parcourt X de droite à gauche
> b:=10^m*X[k]+q; # produit par 10ˆm et ajout de la retenue.
> X[k]:=b mod k; # on laisse le reste en place
> q:=floor(b/k); # c’est la prochaine retenue
> od;
> X[1]:=10^m*X[1]+q; # c’est la partie entière de (10ˆm)x
> RETURN();
> end:
A titre d’exemple, on va appliquer cette procédure à une approximation de e.
n
P 1
Pour tout n ≥ 1, posons en = 2 + k! = (2, 1, . . . , 1)b (le chiffre 1 apparaı̂t n−1 fois.)
k=2
+∞
P 1
On sait que la suite ( en ) converge vers e = 2 + k! .
k=2
On crée le tableau X contenant la représentation de e10 dans la base B :
> X:=array([2,1$9]);
X := [2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
9
P 1
Avec la fonction todec, on calcule la valeur exacte du rationnel e10 = 2 + k! .
k=2
> e[10]:=todec(X,10);
9864101
e10 :=
3628800
Voici une valeur approchée de e10 . On calcule ici les 40 premières décimales.
> e[10]:=evalf(e[10],41);

Page 33 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

e10 := 2.7182818011463844797178130511463844797178
Dans les calculs suivants, on a recours à la variable Y pour former des copies du tableau
X initial (rappelons que la procédure goutte modifie le tableau qui lui est transmis.)
Sur ce premier exemple, on convertit 10 e10 dans la base B.
Dans le tableau obtenu, la première composante est la partie entière de 10 e10 .
> Y:=copy(X): goutte(Y,1); eval(Y);
[27, 0, 1, 0, 1, 5, 4, 3, 2, 0]
On convertit maintenant 1010 e10 . On voit apparaı̂tre les 10 premières décimales de e10 .
> Y:=copy(X): goutte(Y,10); eval(Y);
[27182818011, 0, 2, 3, 0, 3, 6, 6, 2, 0]
On convertit ici 1040 e10 , et on retrouve les 40 premières décimales de e10 . Si ce calcul est
possible en une fois, c’est évidemment grâce aux possibilités arithmétiques de Maple.
> Y:=copy(X): goutte(Y,40); eval(Y);
[27182818011463844797178130511463844797178, 0, 0, 3, 0, 3, 6, 6, 2, 0]
On peut en fait obtenir le même résultat, mais par étapes (notamment si on travaille
sur un système qui ne supporte qu’une arithmétique limitée des entiers.) Dans le calcul
ci-dessous, et à quatre reprises, on annule le premier coefficient de Y (ce qui revient à
s’assurer que le réel y figurant dans ce tableau est compris entre 0 et 1) puis on convertit
1010 y dans la base B (cette valeur remplace la valeur précédente de y).
Chaque étape fournit, dans Y [1], 10 décimales supplémentaires du nombre e10 .
> Y:=copy(X): for k to 4 do Y[1]:=0; goutte(Y,10); print(Y); od:
[7182818011, 0, 2, 3, 0, 3, 6, 6, 2, 0]
[4638447971, 1, 1, 2, 3, 4, 3, 6, 2, 0]
[7813051146, 0, 2, 1, 1, 0, 5, 6, 2, 0]
[3844797178, 0, 0, 3, 0, 3, 6, 6, 2, 0]
On voit que ce calcul pourrait être poursuivi indéfiniment. On obtiendrait ainsi autant de
décimales qu’on le souhaite pour le nombre e10 . Evidemment, et si c’est le nombre e qui
nous intéresse, seules sont dignes d’intérêt les décimales communes de e et de e10 .
1
Or 0 < e − e10 < 10! < 3e-7. Donc e et e10 ont a priori six décimales communes.
En fait e ≈ 2.71828182846 et e10 ≈ 2.71828180114 (sept décimales communes.) [ Q ]
vn+1
(c) Pour tout n ≥ 1, posons vn = n!10−(n+1) . On a = n+1
10 .
vn
La suite (vn ) est donc croissante à partir de n = 9. D’autre part v27 ≈ 1.09 > 1.
1
Pour ≥ 27, on a donc n! < 10−(n+1) . On en déduit 0 < e − en < 10−(n+1) .

Page 34 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Les nombres e et en ont donc les mêmes n premières décimales, sauf erreur d’arrondi
finale. Voici la fonction chiffres e, qui donne n décimales du nombres e, obtenues par
tranches de m décimales successives.
> chiffres_e:=proc(n::integer,m::integer)
> local X,s,t;
> s:="2,"; # initialise la chaı̂ne de caractères
> X:=vector(max(n,27),1); # vecteur de taille n, coefficients=1
> to ceil(n/m) do # au moins n/m fois de suite
> X[1]:=0; # annule la partie entière
> goutte(X,m); # multiplie par 10ˆm et convertit
> t:=convert(10^m+X[1],string); # extrait la partie entière
> s:=cat(s,substring(t,2..m+1)); # ajoute les m nouveaux chiffres
> od;
> RETURN(substring(s,1..n+2)) # renvoie la chaı̂ne, avec n décimales
> end:
Maple nous donne ici le nombre e avec 54 chiffres significatifs (donc 53 décimales.)
La fonction chiffres e nous donne ensuite le même résultat.
Les décimales sont ici obtenues par tranches de 5, mais ça n’influe pas sur le résultat final.
> convert(evalf(exp(1),54),string);
> chiffres_e(53,5);
”2.71828182845904523536028747135266249775724709369995957”
”2, 71828182845904523536028747135266249775724709369995957”
Si on compare avec le résultat précédent, on voit que notre fonction chiffres e donne
49 décimales exactes, alors que l’arrondi obtenu par la fonction intégrée de Maple produit
une erreur sur les quatre dernières de ces 49 décimales.
> convert(evalf(exp(1),50),string);
> chiffres_e(49,5);
”2.7182818284590452353602874713526624977572470937000”
”2, 7182818284590452353602874713526624977572470936999”
[Q]
3. Le calcul des décimales du nombre π
(a) On rappelle que uk = 3 · 51··72···
· 3 ··· · k
· (2k+1) pour tout k ≥ 1, et u0 = 1.
On se donne une suite (pk )k≥1 , avec 0 ≤ pk ≤ 2k pour tout k ≥ 1.
On rappelle l’hypothèse selon laquelle, pour tout n ≥ 1, il existe n0 ≥ n tel que pn0 < 2n0 .
k
Pour tout k ≥ 1, on a uk = 2k+1 uk−1 donc kuk = kuk−1 − (k + 1)uk .
Pour tous entiers 1 ≤ n ≤ m, on peut alors écrire :
m
P m
P Pm
0≤ pk uk ≤ 2 kuk = 2 (kuk−1 − (k+1)uk ) = 2(nun−1 − (m+1)um )
k=n k=n k=n

Page 35 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

Pour tout m ≥ 1, on a um = 3 · 51··72···


· 3 ··· · m
· (2m+1) ≤ 2
−m
. On en déduit lim (m+1)um = 0.
m→+∞
+∞
P
Il en découle, pour tout n ≥ 1 : 0 ≤ pk uk ≤ 2n un−1 .
k=n
La dernière inégalité est stricte car pk < 2k pour au moins un entier k ≥ n.
+∞
1 · 2 · 3 ··· · (n−1) (n!)2
pk uk < 2n 3 · 5 · 7 ··· · (2n−1) = 2n+1 (2n)! .
P
Pour tout n ≥ 1, on a obtenu : 0 ≤
+∞ k=n
P
En particulier : 0 ≤ pk uk < 2.
k=1 +∞
P
Les calculs précédents permettent d’écrire k uk = (n+1)un .
k=n+1

Autrement dit (0, 0, . . . , 0, 0, n+1, n+2, . . .)P = (0, 0, . . . , 0, n+1, 0, 0, . . .)P .


| {z } | {z }
n f ois 0 n f ois 0

Il n’y a donc pas unicité de la représentation d’un réel dans le système P.


Ainsi 1 = (1, 0, 0, . . .)P = (0, 1, 2, 3, . . .)P ou 23 = (0, 2, 0, 0, . . .)P = (0, 0, 2, 3, . . .)P .
La partie entière de (p0 , p1 , p2 , . . .) est égale à p0 ou à p0 + 1.
Elle est égale à 1 si (0, p1 , p2 , p3 . . .) ≥ (0, 1, 2, 3, . . .) (ordre lexicographique.) [ Q ]
(b) Voici la fonction todec2, qui utilise bien sûr un schéma de Horner.
> todec2:=proc(X::array)
> local x,k: x:=0;
> for k from size(X) to 1 by -1 do
> x:=X[k]+x*k/(2*k+1);
> od;
> RETURN(x);
> end:
On n’a pas typé l’argument X pour vérifier le fonctionnement sur l’exemple suivant :
> todec2(array([a,b,c,d]));
1 2 2
b+ c+a+ d
3 15 35
Ici on forme un tableau de taille 20, qui va représenter l’approximation π20 de π.
> X:=array([2$20]);
X := [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
On calcule la valeur exacte de π20 , puis sa valeur approchée avec 10 chiffres significatifs.
On compare ensuite avec la valeur approchée de π donnée par Maple.
> pi[20]:=todec2(X); ’pi[20]’=evalf(pi[20]); ’pi’=evalf(Pi);
104908189597696
π20 :=
33393321606645
π20 = 3.141591928
π = 3.141592654

Page 36 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On constate que π20 est une valeur approchée de π à 10−6 près. [ Q ]


n−1
P
(c) Avec les notations de l’énoncé, xn = (p0 , p1 , p2 , . . . , pn−1 , 0, . . .)P = p k uk .
k=0
n−1
On a alors 10m xn =
P m
(10 pk )uk , écriture qu’il faut convertir à une forme régulière.
k=0
On va se servir de l’égalité (2k+1)uk = k uk−1 , valable pour tout k ≥ 1.
– On effectue la division de 10m pn−1 par 2n−1.
cette division s’écrit : 10m pn−1 = qn−1 (2n−1) + rn−1 , avec 0 ≤ rn−1 ≤ 2(n − 1).
n−3
10m xn =
P m
10 pk uk + 10m pn−2 un−2 + (qn−1 (2n−1) + rn−1 ) un−1
k=0
n−3
10m pk uk + (10m pn−2 + (n−1)qn−1 ) un−2 + rn−1 un−1
P
=
k=0

La division s’est donc traduite par une retenue (n−1)qn−1 , reportée sur 10m pn−2 .
– On divise maintenant p0n−2 = 10m pn−2 + (n−1)qn−1 par 2n−3.
Cette division s’écrit p0n−2 = qn−2 (2n−3) + rn−2 , avec 0 ≤ rn−2 ≤ 2(n−2) :
n−4
10m xn = 10m pk uk + (10m pn−3 + (n−2)qn−2 )un−3 + rn−2 un−2 + rn−1 un−1
P
k=0

– On continue ces divisions successives avec retenues.


n−1
A l’avant-dernière étape, on obtient : 10m xn = 10m p0 + (10m p1 + 2q2 ) u1 +
P
rk uk
0 m k=2
Il reste à diviser p1 = 10 p1 + 2q2 par 3, en utilisant 3u1 = u0 = 1.
Cette division s’écrit p01 = 3q1 + r1 , avec r1 ∈ {0, 1, 2}.
n−1 n−1
Finalement, en posant r0 = 10m p0 + q1 : 10m xn = r0 + r1 u1 +
P P
rk u k = rk uk
k=2 k=0
La conversion est terminée, car le développement obtenu est régulier.
Mais dans ce système de numération, on a [10m xn ] = r0 ou [10m xn ] = r0 +1. [ Q ]

(d) Voici la fonction goutte2, qui réalise la conversion étudiée ci-dessus :


> goutte2:=proc(X::array(integer),m::integer)
> local q,k,p; q:=0; # on initialise la retenue
> for k from size(X) to 2 by -1 do # de droite à gauche, sur le tableau X
> p:=10^m*X[k]+k*q; # multiplie par 10ˆm et ajoute la retenue
> X[k]:=p mod (2*k-1); # laisse en place le reste modulo 2k − 1
> q:=floor(p/(2*k-1)); # calcule le retenue suivante
> od;
> X[1]:=10^m*X[1]+q; # dernier report de retenue
> RETURN(); # conversion terminée dans le tableau X
> end:
On forme ici le tableau de taille 21 représentant l’approximation π21 de π.

Page 37 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

On affiche avec Maple les 30 premières décimales de π21 .


> X:=array([2$21]); pi[21]:=todec2(X): evalf(pi[21],31);
X := [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
3.141592298740339632701922496024
Le fait que X[1] soit égal à 2 signifie que π21 = 2, . . . ou π21 = 3, . . .
On annule X[1], ce qui conduit à X = (0, 2, 2, . . .)P représentant un réel x1 de [1, 2[, ce
qui nous assure que π21 = 3, . . . (on va le constater dans l’instruction suivante.)
On convertit donc 105 X dans le système P :
> X[1]:=0: goutte2(X,5); eval(X);
[114158, 2, 2, 0, 7, 3, 8, 10, 9, 6, 2, 5, 13, 17, 11, 5, 27, 34, 0, 29, 2]
Le fait qu’on ait maintenant X[1] > 105 signifie qu’il faut apporter une retenue d’une
unité au seul chiffre connu de π21 jusqu’à présent. Autrement dit on sait que π21 = 3, . . .
En fait X[1] montre maintenant que π21 = 3, 14158 . . . ou π21 = 3, 14159 . . .
Annulons X[1] et convertissons à nouveau 105 X dans le système P :
> X[1]:=0: goutte2(X,5); eval(X);
[122986, 2, 2, 6, 1, 3, 4, 9, 13, 1, 17, 17, 3, 12, 16, 30, 19, 24, 24, 20, 2]
Là encore, on a X[1] > 105 ce qui nous assure que π21 = 3, 14159 . . .
En fait le résultat montre que π21 = 3, 1415922986 . . . ou π21 = 3, 1415922987 . . .
On recommence : on annule X[1] et on convertit 105 X dans le système P :
> X[1]:=0: goutte2(X,5); eval(X);
[140339, 1, 0, 3, 2, 2, 0, 14, 11, 3, 6, 19, 4, 0, 19, 24, 12, 4, 6, 23, 2]
Ce résultat prouve que π21 = 3, 141592298740339 . . . ou π21 = 3, 141592298740340 . . .
On recommence : on annule X[1] et on convertit 105 X dans le système P :
> X[1]:=0: goutte2(X,5); eval(X);
[63269, 1, 3, 5, 3, 4, 3, 7, 3, 14, 15, 4, 18, 8, 20, 0, 21, 7, 17, 35, 2]
Cette fois-ci la nouvelle composante de X[1] est inférieure à 105 .
Le doute sur le dernier chiffre de l’étape précédente est levé : π21 = 3, 141592298740339 . . .

π21 = 3, 14159229874033963269 . . . ou
En fait, on sait maintenant que
π21 = 3, 14159229874033963270 . . .
Voici une nouvelle étape :
> X[1]:=0: goutte2(X,5); eval(X);
[119224, 0, 4, 4, 0, 7, 12, 12, 16, 1, 3, 13, 23, 0, 28, 25, 17, 20, 0, 5, 2]

Page 38 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé


π21 = 3, 1415922987403396327019224 . . . ou
On sait maintenant que
π21 = 3, 1415922987403396327019225 . . .
Voici une nouvelle étape :
> X[1]:=0: goutte2(X,5); eval(X);
[96023, 1, 3, 6, 2, 8, 0, 9, 1, 18, 14, 2, 18, 26, 2, 14, 25, 9, 2, 2, 2]

π21 = 3, 141592298740339632701922496023 . . . ou
On sait donc que
π21 = 3, 141592298740339632701922496024 . . .
L’étape suivante permettrait évidemment de lever le doute sur la dernière décimale. [ Q ]
k
(e) Pour tout k ≥ 1, l’égalité uk = 2k+1 uk−1 donne effectivement uk < 12 uk−1 .
 k−m
On en déduit, pour tout m ≥ 1 et tout k ≥ m : uk ≤ 12 um .
+∞
P +∞
P 1 k−m
 
Il en découle 0 < π − πm = 2 uk < 2um 2 = 4um .
k=m k=m

D’autre part : um = 3 · 51 ·· 72 ...


· 3· ... ·m 2 1 · 2 · 3 · ... ·m 2 −m
·(2m+1) < 3 2 · 4 · 6 · ... ·(2m) = 3 2 .

Montrons maintenant que si m ≥ 10 −n


3 n, alors 0 < π − πm < 5 · 10 .
Pour cela il suffit de vérifier que m ≥ 10 −n
3 n ⇒ 4um < 5 · 10 .
Mais ce résultat sera lui-même une conséquence de m ≥ 10 8
3 n⇒ 3 ·2
−m
< 5 · 10−n .
Il reste donc à vérifier 8 · 2−m < 15 · 10−n c’est-à-dire m ln 2 > n ln 10 + ln 8 − ln 15.
Or lnln10 10 10
2 ≈ 3.32 < 3 . Ainsi m ln 2 > 3 n ln 2 > n ln 10 > n ln 10 + ln 8 − ln 15.
On a donc établi l’implication m ≥ 10 −n
3 n ⇒ 0 < π − πm < 5 · 10 , pour tout n ≥ 1. [ Q ]
h i
(f) Il suffit de choisir m = 10 3 n pour que πm (représenté dans le système P par le tableau
X = [2, . . . , 2] de longueur m) soit une valeur approchée par défaut de π à 5 · 10−n près.
Les deux nombres π et πm ont alors les mêmes m premiers chiffres (sauf erreur d’ar-
rondi éventuelle sur le tout dernier.) Comme nous savons comment former les décimales
successives de πm , il nous est maintenant possible de trouver celles de π.
Voici notre fonction chiffres pi. Elle accepte les paramètres n (nombres de décimales
à calculer) et m (pour obtenir les décimales par tranches de m, après multiplication par
10m et conversion dans le système P.)
> chiffres_pi:=proc(n::integer,m)
> local X,P,s,t,j,k;
> X:=array([2$floor(10*n/3)]); # tableau [2, 2, . . . , 2]
> P:=array(0..ceil(n/m)); P[0]:=2; # futur tableau des tranches de m décimales
> for k from 1 to ceil(n/m) do # au moins n/m tranches de m décimales
> X[1]:=0; goutte2(X,m); # produit par 10ˆm et conversion
> P[k]:=X[1]; j:=k; # nouvelle tranche de décimales
> while P[j]>=10^m do # boucle de report de retenue si débordement

Page 39 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

> P[j]:=P[j]mod 10^m; j:=j-1; P[j]:=P[j]+1;


> od;
> od;
> s:="3,"; for k from 1 to ceil(n/m) do # formation de la chaı̂ne résultat
> t:=convert(10^m+P[k],string);
> s:=cat(s,substring(t,2..m+1));
> od; RETURN(substring(s,1..n+2)) # renvoie la chaı̂ne des n décimales
> end:
On remarquera la boucle while dont le rôle est de propager la retenue dûe au fait (comme
on l’a vu à plusieurs reprises sur l’exemple illustrant la question (d)) que chaque conversion
(après produit par 10m ) peut produire dans X[1] une valeur supérieure ou égale à 10m .
Dans ce cas, il faut augmenter d’une unité la “tranche” des décimales précédemment
calculée. Mais il n’est pas impossible que ce report conduise à la valeur 10m , ce qui nécessite
un (ou plusieurs) reports successifs. En fait il est bien rare que cette retenue se propage
vraiment, sauf peut-être si m = 1 (c’est-à-dire si on procède à des calculs d’une seule
décimale à chaque étape.)
On affiche ici, avec la fonction intégrée evalf, les 60 premières décimales du nombre π (la
dernière est fausse car résultat d’un arrondi. En fait elle vaut 4.)
> convert(evalf(Pi,61),string);
”3.141592653589793238462643383279502884197169399375105820974945”
Avec la fonction chiffres pi, on calcule 60 décimales de π, à raison d’une nouvelle
décimale à chaque étape (on ne voit pas le détail du calcul, mais uniquement le résultat.)
> chiffres_pi(60,1);
”3, 141592653589793238462643383279502884197169399375105820974944”
On obtient le même résultat en procédant par tranches de 5 décimales à chaque étape.
Le calcul est plus rapide que précédemment. On pourrait augmenter encore le second
paramètre (et la rapidité du calcul), mais cela utilise sans doute un peu trop les capacités
arithmétiques de Maple (notamment ses possibilités de calcul sur les grands entiers.)
> chiffres_pi(60,5);
”3, 141592653589793238462643383279502884197169399375105820974944”
Voici pour terminer le calcul des 500 premières décimales de π.
On obtient d’abord le résultat avec la fonction intégrée de Maple :
> convert(evalf(Pi,501),string);

Page 40 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.
Algorithmique avec Maple
Variations sur le schéma de Horner
Corrigé

”3.1415926535897932384626433832795028841971693993751058209749445
9230781640628620899862803482534211706798214808651328230664
7093844609550582231725359408128481117450284102701938521105
5596446229489549303819644288109756659334461284756482337867
8316527120190914564856692346034861045432664821339360726024
9141273724587006606315588174881520920962829254091715364367
8925903600113305305488204665213841469519415116094330572703
6575959195309218611738193261179310511854807446237996274956
735188575272489122793818301194913”
On calcule maintenant ces décimales avec notre fonction chiffres pi.
> chiffres_pi(500,5);
”3, 1415926535897932384626433832795028841971693993751058209749445
9230781640628620899862803482534211706798214808651328230664
7093844609550582231725359408128481117450284102701938521105
5596446229489549303819644288109756659334461284756482337867
8316527120190914564856692346034861045432664821339360726024
9141273724587006606315588174881520920962829254091715364367
8925903600113305305488204665213841469519415116094330572703
6575959195309218611738193261179310511854807446237996274956
735188575272489122793818301194912”
[Q]

Page 41 Jean-Michel Ferrard www.klubprepa.net EduKlub


c S.A.
Tous droits de l’auteur des œuvres réservés. Sauf autorisation, la reproduction ainsi que toute utilisation des œuvres autre que la consultation
individuelle et privée sont interdites.