MAT231 Feuille de TP n 1 Eléments de réponses aux exercices 00 2007-10-04-mat231_tp01_exemples_programmes.mws (MAPLE 6) Exemples de programmes en réponse aux exercices Exercice 1 (cacul de factorielle n) Donner une procédure pour calculer factorielle n (y compris pour n=0). Solution élémentaire fact:=proc(n::integer) local a,k; # On spécifie que n doit être un entier if n=0 then 1 ; else a:=1 ; for k from 1 to n do a:=a*k od; fi; fact(0); fact(5); fact(5.1); 120 Error, fact expects its 1st argument, n, to be of type integer, but received 5.1 1 Solution utilisant la récursivité restart; fact1:=proc(n::integer); if n=0 then 1; else n*fact1(n-1) fi fact1(0); fact1(5); fact1(1.5); 120 Error, fact1 expects its 1st argument, n, to be of type integer, but received 1.5 1
Cas des grands entiers Si n est très grand, Maple peut retourner un message d'erreur fact1(2000); Error, (in fact1) too many levels of recursion La version ci-dessous, qui utilise l'option remember, permet de faire le calcul de proche en proche. restart: fact2:=proc(n::integer); if n=0 then 1; else n*fact2(n-1) fi fact2(500); fact2(1000); 12201368259911100687012387854230469262535743428031928421924135883\ 85845373153881997605496447502203281863013616477148203584163378722\ 07817720048078520515932928547790757193933060377296085908627042917\ 45478824249127263443056701732707694610628023104526442188787894657\ 54777149863494367781037644274033827365397471386477878495438489595\ 53753799042324106127132698432774571554630997720278101456108118837\ 37095310163563244329870295638966289116589747695720879269288712817\ 80070265174507768410719624390394322536422605234945850129918571501\ 24870696156814162535905669342381300885624924689156412677565448188\ 65065938479517753608940057452389403357984763639449053130623237490\ 66445048824665075946735862074637925184200459369692981022263971952\ 59719094521782333175693458150855233282076282002340262690789834245\ 17120062077146409794561161276291459512372299133401695523638509428\ 85592018727433795173014586357570828355780158735432768888680120399\ 88238470215146760544540766353598417443048012893831389688163948746\ 96588175045069263653381750554781286400000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000 40238726007709377354370243392300398571937486421071463254379991042\ 99385123986290205920442084869694048004799886101971960586316668729\ 94808558901323829669944590997424504087073759918823627727188732519\ 77950595099527612087497546249704360141827809464649629105639388743\ 78864873371191810458257836478499770124766328898359557354325131853\
23958463075557409114262417474349347553428646576611667797396668820\ 29120737914385371958824980812686783837455973174613608537953452422\ 15865932019280908782973084313928444032812315586110369768013573042\ 16168747609675871348312025478589320767169132448426236131412508780\ 20800026168315102734182797770478463586817016436502415369139828126\ 48102130927612448963599287051149649754199093422215668325720808213\ 33186116811553615836546984046708975602900950537616475847728421889\ 67964624494516076535340819890138544248798495995331910172335555660\ 21394503997362807501378376153071277619268490343526252000158885351\ 47331611702103968175921510907788019393178114194545257223865541461\ 06289218796022383897147608850627686296714667469756291123408243920\ 81601537808898939645182632436716167621791689097799119037540312746\ 22289988005195444414282012187361745992642956581746628302955570299\ 02432415318161721046583203678690611726015878352075151628422554026\ 51704833042261439742869330616908979684825901254583271682264580665\ 26769958652682272807075781391858178889652208164348344825993266043\ 36766017699961283186078838615027946595513115655203609398818061213\ 85586003014356945272242063446317974605946825731037900840244324384\ 65657245014402821885252470935190620929023136493273497565513958720\ 55965422874977401141334696271542284586237738753823048386568897646\ 19273838149001407673104466402598994902222217659043399018860185665\ 26485061799702356193897017860040811889729918311021171229845901641\ 92106888438712185564612496079872290851929681937238864261483965738\ 22911231250241866493531439701374285319266498753372189406942814341\ 18520158014123344828015051399694290153483077644569099073152433278\ 28826986460278986432113908350621709500259738986355427719674282224\ 87575867657523442202075736305694988250879689281627538488633969099\ 59826280956121450994871701244516461260379029309120889086942028510\ 64018215439945715680594187274899809425474217358240106367740459574\ 17851608292301353580818400969963725242305608559037006242712434169\ 09004153690105933983835777939410970027753472000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000 Exercice 2 (Nombres s)
Ecrire des programmes pour déterminer les nombres s inférieurs ou égaux à un nombre donné N : (i) programme utilisant la fonction isprime de MAPLE (cf aide en ligne) ; (ii) programme simulant le crible d'eratosthène ; (iii) programme utilisant irem mais pas isprime. Algorithme utilisant la fonction isprime # Affiche des N s nombres s avec "isprime" nbs_prem1:=proc(n) local S,p: S:={2}; for p from 3 to N by 2 do if isprime(p) then S:=[op(S), p]; fi; od; RETURN(S); nbs_prem1(100); [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ] Crible d'ératosthène erath1:=proc(n::integer) local A,m,i,j,k,P: for i from 2 to N do A[i]:=true od: m:=floor(sqrt(n)): # Ici on utilise le fait qu'il suffit de tester les # nombres jusqu'à sqrt(n) seulement. for i from 2 to m do if A[i] then for j from 2 to iquo(n,i) do A[i*j]:=false od: fi: od: for i from 2 to N do if A[i] then print(i, ``) fi: od: erath1(100); 2, 3, 5, 7,
11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, Avec la fonction irem # Affichage des N s nombres s # crible d'eratosthène amélioré nbs_prem3:=proc(n) local S,p,q,m,a: S:={2}:a:= ceil(sqrt(n)): for p from 3 to N by 2 do q:=1; for m in S do if (m <= a) then if (irem(p,m)=0) then q:=q*0; else q:=q*1; fi; fi; od; if (q=1) then S:=[op(S), p]; fi; od; RETURN(S);
nbs_prem3(100); [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ] Exercice 3 (Décomposition en facteurs s) Ecrire un programme factorisant un nombre donné N en facteurs s en utilisant la fonction nextprime de Maple. Décomposition en facteurs s decomp:=proc(n::integer) local A,M,a,n,q,B,E,C: with(linalg): A:= matrix([[nb_],[exposant]]): # N:=11*13: M:=N: # N:=2^2*3^7*11*2*17*19^2:M:=N: M:=N: a:=2: n:=1: while ((M < 1) and (a^2 <= N)) do if (irem(m,a) = 0) then q:=1: while (irem(m,a) = 0) do M:=M/a: q:=q+1: od: B:= matrix([[a],[q-1]]): A:=augment(A,B): fi: a:=nextprime(a): n:=n+1: od: E:=matrix([[M],[1]]): if M<1 then A:=augment(A,E) fi: C:=matrix([[Nb,N],[Decomp,ifactor(N)]]): A:=augment(A,C): decomp(2^5*3^7*11*2*17*19^3*503); Nb_, 2, 3, 11, 17, 19, 503, Nb, 90302370599232 Exposant, 6, 7, 1, 1, 3, 1, Decomp, ( 2 ) 6 ( 3) 7 ( 11 ) ( 17 ) ( 19) 3 ( 503 ) Exercice 4 (Division euclidienne) (i) Ecrire un programme donnant le quotient et le reste de la division euclidienne de a par b
et vérifiez vos résultats à l'aide des fonctions Maple iquo(a,b) et irem(a,b). (ii) Ecrire ce programme sous forme de procédure. Introduire un contrôle de temps d'exécution en utilisant la fontion Maple time(). (iii) On suppose que le nombre a est très grand devant le nombre b (par exemple a/b 10.000.000). Donner une estimation du nombre d'opérations (addition / soustractions / multiplications) nécessaires pour exécuter votre procédure. [Réponse : O(a) opérations] Division euclidienne, version soustractive (procédure avec contrôle de temps d'exécution) #division euclidienne / par soustration div_euc1:=proc(a,b) local k,q,r,u,t; r:=a : q:= 0:t:=time(): while (r = b) do r:=r-b: q:=q+1: od: u:=array(1..2,1..5,[[nombre_a, Nombre_b, Quotient, Reste, Temps],[a,b,q,r,time()-t]]): print(u): div_euc1(1597,27); div_euc1(1123456789,567); div_euc1(11234567897,567); Nombre_a Nombre_b Quotient Reste Temps 1597 27 59 4 0. 1123456789 567 1981405 154 2.623 11234567897 567 19814052 413 34.500 Exercice 5 (Division euclidienne revisitée) Pour réduire le temps de calcul dans l'algorithme de division euclidienne, on cherche le quotient q de la division euclidienne de a par b sous forme binaire. 1. Donner un algorithme mettant en oeuvre cette idée. 2. Donner une estimation du nombre d'opérations nécessaires. Version par dichotomie binaire (procédure et avec contrôle de temps d'exécution)
# Division euclidienne par dichotomie binaire (non optimisée) div_euc3:=proc(a,b) local q,r,n,p,k,u,v,w,t; r:=a : q:=0 : n:=0 : v:=b: t:= time() : while (v <= a) do v:= 2*v : n:=n+1 : od: # A la fin de cette étape : r vaut a ; # q vaut 0 ; n vaut p tel que v vaut 2^p*b # et 2^(p-1)*b =< a < 2^p*b ; # On va écrire q, "en base 2", sous la forme # q = 2^(p-1) +... p:=n : w:=array(1..p) : w[p]:=1 : while (n0) do v:=v/2 : n:=n-1 : if (r<v) then w[n+1]:=0 : else w[n+1]:=1 : r:=r-v : fi: od: q:= sum(w[k]*2^(k-1),k=1..p) : r:= a-b*q : u:=array(1..2,1..5,[[nombre_a, Nombre_b, Quotient, Reste, Temps],[a,b,q,r,time()-t]]): print(u); div_euc3(1597,27); div_euc3(1123456789,567); div_euc3(11234567897,567); Nombre_a Nombre_b Quotient Reste Temps 1597 27 59 4.081 1123456789 567 1981405 154 0. 11234567897 567 19814052 413 0. Estimation du nombre d'opérations : O(log(a)²) Version par dichotomie binaire (procédure, méthode de Hörner, contrôle de temps d'exécution) # Division euclidienne par dichotomie binaire + Hörner
div_euc4:=proc(a,b) local q,r,n,u,v,t; r:=a : q:=0 : n:=0 : v:=b: t:= time() : while (v <= a) do v:= 2*v : n:=n+1 : od: # A la fin de cette étape, on a r vaut a ; # q vaut 0 ; n vaut p tel que v vaut 2^p*b et # 2^(p-1)*b =< a < 2^p*b ; while (n0) do v:=v/2 : n:=n-1 : if (r<v) then q:=2*q : else q:=2*q+1:r:=r-v: fi: od: # Dans cette étape, on a calculé q en utilisant la # méthode de Hörner u:=array(1..2,1..5,[[nombre_a, Nombre_b, Quotient, Reste, Temps],[a,b,q,r,time()-t]]): print(u); div_euc4(1597,27); div_euc4(1123456789,567); div_euc4(11234567897,567); Nombre_a Nombre_b Quotient Reste Temps 1597 27 59 4 0. 1123456789 567 1981405 154 0. 11234567897 567 19814052 413 0. Estimation du nombre d'opérations : O(log(a))