Examen sur la programmation fonctionnelle - correction, Examens de Application informatique. Ecole des Ingénieurs de la Ville de Paris
Christophe
Christophe

Examen sur la programmation fonctionnelle - correction, Examens de Application informatique. Ecole des Ingénieurs de la Ville de Paris

4 pages
300Numéro de visites
Description
Exercices de mathématique de l'ingénieur sur la programmation fonctionnelle - correction. Les principaux thèmes abordés sont les suivants: exercices.
20 points
Points de téléchargement necessaire pour télécharger
ce document
Télécharger le document
Aperçu3 pages / 4
Ceci c'est un aperçu avant impression
3 pages affichées sur 4 total
Télécharger le document
Ceci c'est un aperçu avant impression
3 pages affichées sur 4 total
Télécharger le document
Ceci c'est un aperçu avant impression
3 pages affichées sur 4 total
Télécharger le document
Ceci c'est un aperçu avant impression
3 pages affichées sur 4 total
Télécharger le document
en_pac2005.dvi

E.N.S.E.I.R.B.Filière Informatique 1ère année Année 2005-2006PROGRAMMATION IMPÉRATIVE - LANGAGE C AVANCÉEXAMENCORRIGÉN.B. : - Ce i doit être onsidéré omme un orrigé-type : les réponses qu'il ontient sont justes, maisleur réda tion n'était pas la seule possible.- Le barème est donné à titre dénitif. Outre l'exa titude des réponses aux questions posées,il a été tenu ompte de leur on ision et, dans une moindre mesure, de la présentation.Question 1. (4 points)La validité et la robustesse sont deux fa teurs de qualité externe d'un programme.La validité est la apa ité d'un programme à remplir sa fon tion dans le respe t des spé i ations. Lavalidité peut être évaluée de façon empirique (jeux de tests) et/ou formelle (preuve de programmes).La robustesse est la apa ité d'un programme à fon tionner en dehors du domaine prévu dans les spé i- ations. Elle est prin ipalement liée à la qualité de la programmation.Validité et robustesse sont liées en e qu'elle portent toutes deux sur le fon tionnement orre t duprogramme, l'une dans le adre des spé i ations, et l'autre en dehors. Plus on étend et pré ise lesspé i ations, et plus le domaine de fon tionnement relevant de la validité s'étend, re ouvrant des zonesqui relevaient auparavant de la robustesse.Question 2. (16 points)(2.1) (3 points)Dans les spé i ations, il est dit que la fon tion premSuivant renvoie le premier nombre premierstri tement supérieur au nombre qui lui est passé en paramètre. On va s'appuyer sur es spé i ationspour tester la primalité du nombre passé en paramètre, en vériant que premSuivant onsidère bien e nombre omme un nombre premier.intpremVerifie (int prem){ return (premSuivant (prem - 1) != prem); /* Renvoie 0 si pas erreur */}Cette version n'est pas satisfaisante, par e qu'il est fort probable que le nombre à vérier aura lui-même été obtenu au moyen de la fon tion premSuivant. Si elle- i est boguée, et renvoie par exempleun nombre qui n'est pas premier, elle peut très bien le refaire une deuxième fois. Il faut don testerla primalité d'un nombre de façon autonome. La routine peut, en première approximation, ne pasêtre e a e en temps, ar 'est une routine de débogage qui ne restera sans-doute pas a tive dans laversion de produ tion. Si elle est nalement jugée trop ine a e, il faudra en fournir ultérieurementune version plus optimisée.intpremVerifie (int prem){ int divi;for (divi = 2; divi * divi <= prem; divi ++) {if ((prem % divi) == 0)return (1);} 1

return (0); /* Renvoie 0 si pas erreur */}On pouvait déjà l'optimiser d'un fa teur deux en temps en ne testant que les nombres impairs.intpremVerifie (int prem){ int divi;if (prem == 2) /* Si égal à deux, premier */return (0);if ((prem & 1) == 0) /* Si pair, pas premier */return (1);for (divi = 3; divi * divi <= prem; divi += 2) {if ((prem % divi) == 0)return (1);}return (0);}(2.2) (2 points)Les spé i ations de la fon tion premSuivant sont assez stri tes, et peuvent donner lieu à nombrede tests unitaires. On peut vérier par exemple : si l'appel de premSuivant sur des nombres pris au hasard donne bien toujours des nombres pre-miers ; si, entre le nombre pris au hasard et le nombre premier renvoyé par premSuivant, au un nombren'est premier.On en dérive le ode suivant, en s'appuyant sur la routine premVerifie déjà à notre disposition. Lesmessages d'erreur sont destinés à pouvoir reproduire et analyser les erreurs ren ontrées.main (){ while (1) { /* Ou bou le sur un nombre d'essais */int rnum; /* Nombre aléatoire */rnum = intrandom (); /* Fon tion annexe qui renvoie un entier positif */prem = premSuivant (rnum);if (premVerifie (prem) != 0) {printf ("Le nombre %d n'est pas premier\n", prem);exit (1);}for (intr = rnum + 1; intr < prem; intr ++) {if (premVerifie (intr) == 0) {printf ("Le nombre %d est premier mais pas vu depuis %d\n", intr, rnum);exit (1);}}}}(2.3) (3 points)Rien n'est su a priori sur l'usage qui sera fait de la lé. Rien n'est non plus dit sur la omplexitéde la fon tion premSuivant, e qui fait qu'on ne peut pas être sûr s'il est mieux de re al uler lesnombres premiers à haque fois, ou s'il est préférable de les sto ker lors de la génération de la lé.La dé ouverte de grands nombres premiers n'étant ependant pas triviale, on s'orientera don pluttvers la deuxième solution. Une lé sera don dénie sous la forme d'une stru ture donnant le nombrede nombres premiers onsé utifs sto kés, ainsi que le pointeur sur un tableau dynamique servantà onserver es nombres. Les nombres entiers onstituant la lé étant fournis par la routine premSuivant, on peut spé ier, même si ela n'a pas d'importan e pour le moment, que es nombresseront triés par valeurs roissantes dans le tableau. La valeur minimum sera impli itement onservéeen tant que première valeur du tableau. La valeur maximum ne sera pas onservée, mais pourratoujours être obtenue en appelant premSuivant ave omme paramètre la dernière valeur du tableau.S'il est né essaire de la onserver pour y a éder rapidement, on pourra toujours modier la stru ture2

de lé pour la onserver dans la stru ture, ou bien omme nouvelle dernière valeur du tableau des lés. On peut don dénir le type Cle de la façon suivante.typedef stru t Cle_ {int premnbr; /* Nombre de nombres premiers */int * premtab; /* Tableau des nombres premiers */} Cle;Parmi les méthodes qui pourraient lui être appliquées, on peut iter : leInit : routine d'initialisation de la lé ; leExit : routine de destru tion de la lé ; leVerifie : routine de veri ation de la ohéren e des données internes de la lé ; lePremNbr et lePremVal : a esseurs renvoyant respe tivement le nombre de nombres premiersprésents dans la lé, et le nombre premier d'indi e passé en paramètre. Ces a esseurs permettentde masquer aux modules lients l'implémentation du type Cle.(2.4) (2 points)La fon tion leInit peut s'é rire de la façon i-dessous. Comme on suppose que le al ul des nombrespremiers par premSuivant est oûteux, on les sto ke dans un tableau dynamique an d'éviter d'avoirà les re al uler deux fois ( ar il faudrait sinon les al uler une première fois pour en déterminer lenombre, puis une deuxième fois pour remplir le tableau après avoir alloué elui- i ave la bonnetaille). La réallo ation du tableau est optimisée pour qu'elle ne prenne pas trop de temps.int leInit (Cle * leptr,int premmin,int premmax){ int premnbr; /* Nombre de nombres premiers trouvés */int premmax; /* Taille ourante du tableau dynamique */int * premtab; /* Pointeur sur le tableau dynamique */int premnum; /* Nombre premier a tuellement traité */premmax = 20; /* On augmentera de 20 en 20 */if ((premtab = mallo (premmax * sizeof (int))) == NULL)return (1);premnbr = 0; /* Rien dans le tableau pour le moment */for (premnum = premmin - 1; premnum < premmax; premnum = premSuivant (premnum)) {if (premnbr == premmax) { /* Si plus de pla e */int * premtmp;premmax += 20; /* On rajoute 20 de plus */premtmp = premtab; /* Garde tra e de l'an ien */if ((premtab = reallo (premtab, premmax * sizeof (int))) == NULL) {free (premtmp); /* Libère l'an ien si plus de mémoire */return (1);}}premtab[premnbr ++℄ = premnum;} leptr->premnbr = premnbr; leptr->premtab = premtab;return (0);}(2.5) (2 points)La fon tion leVerifie a pour objet de tester la ohéren e des données ontenues dans la stru tureCle qui lui est passée en paramètre. On testera don si tous les nombres de la lé sont bien premiers,triés ( 'est une spé i ation que nous avons ajoutée, mais qui nous sert bien en l'o uren e puisqu'ellenous évite d'avoir à les trier au moment de la omparaison ave les résultats su essifs de premSuivant, dont les appels renvoient impli itement les nombres premiers dans l'ordre roissant). On neretestera pas i i la validité des résultats de premSuivant, puisque e n'est pas l'objet de e module.3

int leVerifie (Cle * leptr){ int premidx;int premnum; /* Nombre premier a tuellement traité */if ( leptr->premnbr <= 0) /* Il doit y avoir au moins un nombre */return (1);for (premidx = 1; premidx < leptr->premnbr; premidx ++) {if (premSuivant ( leptr->premtab[premidx - 1℄) != leptr->premtab[premidx℄)return (1);}return (0);}(2.6) (2 points)Le module Cle est un module de servi e, enfoui, dont on ne onnait pas l'utilisation. Il serait don malvenu de traiter les erreurs en a hant des informations intempestives à l'é ran, ou bien en pro-voquant la terminaison du programme appelant. Les seuls a hages que l'on s'autorise sont dans lesroutines de véri ation, qui servent au débogage, et pour lesquelles on solli ite un retour d'informa-tion maximal. Pour le reste des routines, on emploiera les odes de retour pour signaler d'éventuelleserreurs.(2.7) (2 points)On ne dispose d'au une information sur la manière dont sera utilisé le module Cle. Pour le moment,les seules routines dont on dispose sont leInit et leVerifie, sur lesquelles porteront don lestests. Ces tests porteront sur la génération et la véri ation de lés générées aléatoirement, et dontla taille sera bornée.#define TAILMAX 1000 /* Taille maximale d'une lé */main (){ Cle ledat; /* Stru ture de lé */while (1) { /* Ou bou le sur un nombre d'essais */int premmin; /* Premier nombre premier de la lé */int premmax; /* Dernier nombre premier de la lé */int tailval; /* Taille aléatoire de la lé */premmin = premSuivant (intrandom ()); /* Nombre premier aléatoire */tailval = (intrandom () % TAILMAX) + 1; /* Taille toujours >= 1 */for (premmax = premmin; tailval > 0; tailval --)premmax = premSuivant (premmax); /* Re her he de la borne supérieure */if ( leInit (& ledat, premmin, premmax) != 0) {printf ("Erreur de réation de lé : %d %d\n", premmin, premmax);exit (1);}if ( leVerifie (& ledat) != 0) {printf ("Clé non onforme : %d %d\n", premmin, premmax);exit (1);} leExit (& ledat); /* Ne pas oublier de libérer la mémoire */}} 4

Aucun commentaire n'a été pas fait
Ceci c'est un aperçu avant impression
3 pages affichées sur 4 total
Télécharger le document