Nous savons maintenant repr´esenter les polynˆomes `a l’aide des tableaux. Pour les manipuler, nous savons parcourir leurs coefficients `a l’aide d’une boucle for. Nous pou- vons donc commencer l’impl´ementation des op´erations ´el´ementaires sur les polynˆomes. Commen¸cons par ´ecrire une proc´edure d’impression des polynˆomes pour visualiser simplement nos r´esultats. Il suffit de parcourir le tableau repr´esentant le polynˆome en imprimant ses monˆomes. Nous ´ecrivons donc d’abord la fonction d’impression d’un
Impression des polynˆomes 43 monˆome de coefficient c et de degr´e d. C’est tr`es simple : si le degr´e est 0, il suffit d’´ecrire le coefficient ; sinon, on ´ecrit le coefficient et le degr´e sous la forme cX^d. Par exemple, 3x2 sera ´ecrit 3x^2. Cet imprimeur n’est pas tr`es ´elabor´e : il se contente de
ne pas ´ecrire les monˆomes nuls ni les coefficients ´egaux `a 1 ; il traite aussi sp´ecialement le cas particulier des monˆomes de degr´e 0 et 1. Ainsi il ´ecrit x^2 pour le monˆome 1x2, 3pour le monˆome 3x0 et 4x pour le monˆome 4x1.
# let imprime_mon^ome coeff degr´e =
if degr´e = 0 then print_int coeff else if coeff <> 0 then
begin
print_string " + ";
if coeff <> 1 then print_int coeff; print_string "x";
if degr´e <> 1 then
begin print_string "^"; print_int degr´e end end;;
imprime_mon^ome : int -> int -> unit = <fun>
La primitive <> correspond au pr´edicat math´ematique 6= et teste donc si deux valeurs sont diff´erentes.
Il est temps de donner le nom technique des polynˆomes mod´elis´es par des tableaux d’entiers : on les appelle polynˆomes pleins, ce qui signifie simplement que leur repr´esentation comporte la liste exhaustive de leurs monˆomes, y compris ceux dont le coefficient est nul. C’est pourquoi nous appelons la fonction d’impression de ces polynˆomes imprime_polyn^ome_plein. Cette fonction se contente d’it´erer la proc´edure imprime_mon^ome sur tout le polynˆome, `a l’aide d’une boucle « pour ».
# let imprime_polyn^ome_plein p =
for i = 0 to vect_length p - 1 do imprime_mon^ome p.(i) i done;; imprime_polyn^ome_plein : int vect -> unit = <fun>
Le polynˆome p = x2+ 2x + 3 s’imprime comme suit :
# imprime_polyn^ome_plein p;; 3 + 2x + x^2- : unit = ()
Addition des polynˆomes
L’addition des polynˆomes se fait monˆome par monˆome, en ajoutant les coefficients des monˆomes de mˆeme degr´e :
(1 + 2x + 3x2) + (4 + 5x + 6x2) = (1 + 4) + (2 + 5)x + (3 + 6)x2 = 5 + 7x + 9x2.
Math´ematiquement, on a : si P = p0+ p1x + p2x2+ · · · + pmxm et Q = q0+ q1x +
q2x2+ · · · + qnxn, alors
P + Q = (p0+ q0) + (p1+ q1)x + (p2+ q2)x2+ · · · + (pmax(m,n)+ qmax(m,n))xmax(m,n)
Cette d´efinition utilise la convention qu’un coefficient de degr´e sup´erieur au degr´e du polynˆome est implicitement 0. On peut exprimer ces formules de fa¸con plus synth´etique
en introduisant la notation math´ematique Σ pour r´esumer les sommes de termes : si formule est une expression qui d´epend de l’entier i, on note
n X i=0
formule(i) pour formule (0) + formule (1) + · · · + formule (n).
(La notation Pni=0formule(i) se lit « somme de i ´egale 0 `a n de formule (i) ».) Par exemple, si la formule est r´eduite `a i, on obtient la somme des nombres de 0 `a n :
n X i=0
i = 0 + 1 + · · · + n.
De mˆeme, si la formule est i2, la somme correspondante est celle des carr´es des nombres entre 0 et n :
n X i=0
i2 = 02+ 12+ · · · + n2.
On exprime ainsi de mani`ere tr`es concise deux polynˆomes g´en´eraux P et Q et leur somme P + Q : Si P = m X i=0 pixi et Q = n X i=0 qixi alors P + Q = max(m,n) X i=0 (pi+ qi) xi.
La traduction en Caml de cette d´efinition est tr`es simple : on cr´ee d’abord un tableau somme, pour contenir la somme des deux polynˆomes P et Q. Ce tableau a pour longueur le maximum des longueurs de P et Q, qu’on calcule avec la fonction pr´ed´efinie max. Il suffit de recopier les coefficients de l’un des polynˆomes dans les cases du r´esultat, puis d’y ajouter les coefficients de l’autre.
# let ajoute_polyn^omes_pleins p q =
let somme = make_vect (max (vect_length p) (vect_length q)) 0 in for i = 0 to vect_length p - 1 do
somme.(i) <- p.(i) done;
for i = 0 to vect_length q - 1 do somme.(i) <- somme.(i) + q.(i) done;
somme;;
ajoute_polyn^omes_pleins : int vect -> int vect -> int vect = <fun>
Comme promis, nous pouvons maintenant calculer la valeur de 2x + 2x :
# imprime_polyn^ome_plein (ajoute_polyn^omes_pleins [|0; 2|] [|0; 2|]);; 0 + 4x- : unit = ()
et v´erifier un de nos calculs pr´ec´edents :
# imprime_polyn^ome_plein
(ajoute_polyn^omes_pleins [|1; 2; 3|] [|4; 5; 6|]);; 5 + 7x + 9x^2- : unit = ()
et mˆeme (qui l’eˆut cru ?) calculer x − x et trouver 0 :
# imprime_polyn^ome_plein
(ajoute_polyn^omes_pleins [|0; 1|] [|0; -1|]);; 0- : unit = ()
Impression des polynˆomes 45
Multiplication des polynˆomes
On d´efinit le produit des polynˆomes en utilisant les r`egles classiques de d´eveloppement des expressions alg´ebriques. En termes savants, on dit que l’on utilise la distributivit´e de la multiplication par rapport `a l’addition. Par exemple, pour tout polynˆome Q, on a (1 + 2x + 3x2) × Q = 1 × Q + 2x × Q + 3x2× Q, et donc
(1 + 2x + 3x2) × (4 + 5x + 6x2)
= 1 × (4 + 5x + 6x2) + 2x × (4 + 5x + 6x2) + 3x2× (4 + 5x + 6x2) = (4 + 5x + 6x2) + (8x + 10x2+ 12x3) + (12x2+ 15x3+ 18x4) = 4 + 13x + 28x2+ 27x3+ 18x4.
La remarque fondamentale est que le produit des coefficients des monˆomes de degr´e i du premier polynˆome et de degr´e j du second forme une partie du coefficient du monˆome de degr´e i + j du produit. Par exemple, pour les monˆomes 2x et 6x2, le produit 2 × 6
entrera dans la composition du coefficient du monˆome de degr´e trois du r´esultat, ce qui signifie simplement que 2x × 6x2 = 12x3. Pour prendre en compte le produit des monˆomes 2x et 6x2dans le r´esultat final, il suffit donc d’ajouter le produit 2 × 6 dans la
case correspondant au coefficient de x3 du r´esultat final. Ainsi, notre proc´edure Caml va parcourir les monˆomes des deux polynˆomes deux `a deux, en les multipliant et en enregistrant le produit de leurs coefficients dans le monˆome de degr´e correspondant du produit.
Pour les fanatiques des formules, ceci se traduit par la d´efinition math´ematique suivante :
Le produit des deux polynˆomes P =
m X i=0 piXi et Q = n X j=0 qjXj
est le polynˆome (P × Q) =
m+n X k=0 rkXk avec rk = X i+j=k pi× qj, ou de fa¸con ´equivalente, (P × Q) = m+n X k=0 k X i=0 pi× qk−i ! Xk.
Remarquez que ces formules d’apparence r´ebarbative ne font que r´esumer de fa¸con tr`es succinte notre explication en fran¸cais, mais en aucun cas ne la rendent inutile.
Pour coder la multiplication des polynˆomes en Caml, le plus difficile est de cal- culer la longueur du tableau r´esultat. On sait cependant que le monˆome de plus haut degr´e du r´esultat a pour degr´e la somme des degr´es des monˆomes de plus haut degr´e des polynˆomes multipli´es. Or, le degr´e du monˆome de plus haut degr´e d’un polynˆome repr´esent´e par un tableau v de longueur l est l − 1. C’est donc, en Caml, vect_length(v) − 1. Par exemple, le polynˆome p = x2 + 2x + 3, est repr´esent´e par un tableau `a trois cases et son monˆome de plus haut degr´e est de degr´e 2. Mais le monˆome de degr´e maximum du produit des polynˆomes p et q a pour degr´e la somme des degr´es des monˆomes de degr´e maximum de p et q, soit (vect_length(p) − 1) + (vect_length(q) − 1). On en d´eduit facilement que le tableau repr´esentant p × q a pour longueur vect_length(p) + vect_length(q) − 1.
# let multiplie_polyn^omes_pleins p q =
let produit = make_vect (vect_length p + vect_length q - 1) 0 in for i = 0 to vect_length p - 1 do
for j = 0 to vect_length q - 1 do
produit.(i + j) <- p.(i) * q.(j) + produit.(i + j) done
done; produit;;
multiplie_polyn^omes_pleins : int vect -> int vect -> int vect = <fun>
Notre programme effectue sans peine le produit des polynˆomes (1 + 2x + 3x2) et (4 + 5x + 6x2) que nous avions pr´ec´edemment calcul´e `a la main.
# imprime_polyn^ome_plein
(multiplie_polyn^omes_pleins [|1; 2; 3|] [|4; 5; 6|]);; 4 + 13x + 28x^2 + 27x^3 + 18x^4- : unit = ()
Comme exemple plus consistant, calculons (x + 1)2 puis (x + 1)4 et (x + 1)8. # let p = [| 1; 1|] in
let p2 = multiplie_polyn^omes_pleins p p in let p4 = multiplie_polyn^omes_pleins p2 p2 in let p8 = multiplie_polyn^omes_pleins p4 p4 in print_string "(x + 1) ** 2 = ";
imprime_polyn^ome_plein p2; print_newline (); print_string "(x + 1) ** 4 = ";
imprime_polyn^ome_plein p4; print_newline (); print_string "(x + 1) ** 8 = ";
imprime_polyn^ome_plein p8; print_newline ();; (x + 1) ** 2 = 1 + 2x + x^2
(x + 1) ** 4 = 1 + 4x + 6x^2 + 4x^3 + x^4
(x + 1) ** 8 = 1 + 8x + 28x^2 + 56x^3 + 70x^4 + 56x^5 + 28x^6 + 8x^7 + x^8 - : unit = ()