• Aucun résultat trouvé

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 = ()