IN TD septembre 2011

Documents pareils
1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

MISE A NIVEAU INFORMATIQUE LANGAGE C - EXEMPLES DE PROGRAMMES. Université Paris Dauphine IUP Génie Mathématique et Informatique 2 ème année

Représentation d un entier en base b

Licence Sciences et Technologies Examen janvier 2010

Le prototype de la fonction main()


Algorithmique et Programmation, IMA

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Introduction au langage C

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Corrigé des TD 1 à 5

Programmation C. Apprendre à développer des programmes simples dans le langage C

Cours d initiation à la programmation en C++ Johann Cuenin

Bases de programmation. Cours 5. Structurer les données

Programmation Classique en langage C

Architecture des ordinateurs

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Programmation C++ (débutant)/instructions for, while et do...while

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

Les structures de données. Rajae El Ouazzani

TD3: tableaux avancées, première classe et chaînes

Feuille TD n 1 Exercices d algorithmique éléments de correction

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

STAGE IREM 0- Premiers pas en Python

Initiation à l algorithmique

INF 321 : mémento de la syntaxe de Java

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Programmation système I Les entrées/sorties

Cryptographie RSA. Introduction Opérations Attaques. Cryptographie RSA NGUYEN Tuong Lan - LIU Yi 1

Cours d algorithmique pour la classe de 2nde

Solutions du chapitre 4

Architecture des ordinateurs TD1 - Portes logiques et premiers circuits

Algorithmes et Programmes. Introduction à l informatiquel. Cycle de vie d'un programme (d'un logiciel) Cycle de vie d'un programme (d'un logiciel)

V- Manipulations de nombres en binaire

Algorithmes récursifs

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Java Licence Professionnelle CISII,

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Plan du cours. Historique du langage Nouveautés de Java 7

Cours de Programmation Impérative: Zones de mémoires et pointeurs

INF111. Initiation à la programmation impérative en C amini/cours/l1/inf111/ Massih-Reza Amini

Programmation en langage C

Recherche dans un tableau

Examen Médian - 1 heure 30

Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS Sommaire

ALGORITHMIQUE ET PROGRAMMATION En C

3IS - Système d'exploitation linux - Programmation système

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Représentation des Nombres

Exercices - Polynômes : corrigé. Opérations sur les polynômes

Programmation système de commandes en C

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Algorithmes et mathématiques. 1. Premiers pas avec Python. Exo Hello world!

Les arbres binaires de recherche

Initiation à la programmation en Python

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Définitions. Numéro à préciser. (Durée : )

Projet L1, S2, 2015: Simulation de fourmis, Soutenance la semaine du 4 mai.

Programmation système en C/C++

Définition 0,752 = 0,7 + 0,05 + 0,002 SYSTÈMES DE NUMÉRATION POSITIONNELS =

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Programmation C. J.-F. Lalande. 15 novembre 2012

1 Recherche en table par balayage

Conventions d écriture et outils de mise au point

Algorithmique et programmation : les bases (VBA) Corrigé

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Exercices types Algorithmique et simulation numérique Oral Mathématiques et algorithmique Banque PT

Probabilités sur un univers fini

Exo7. Calculs de déterminants. Fiche corrigée par Arnaud Bodin. Exercice 1 Calculer les déterminants des matrices suivantes : Exercice 2.

Cryptographie et fonctions à sens unique

Programmation en C. École Nationale Supérieure de Techniques Avancées. Pierre-Alain Fouque et David Pointcheval

I. Introduction aux fonctions : les fonctions standards

Claude Delannoy. 3 e édition C++

avec des nombres entiers

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Lier Erlang avec d autres langages de programmation

COMPARAISONDESLANGAGESC, C++, JAVA ET

Algorithmique, Structures de données et langage C

Langages et Concepts de Programmation Introduction à la programmation en langage C

Introduction à l étude des Corps Finis

Cours de Systèmes d Exploitation

Cours d Algorithmique et de Langage C v 3.0

introduction Chapitre 5 Récursivité Exemples mathématiques Fonction factorielle ø est un arbre (vide) Images récursives

Cours Informatique Master STEP

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

Principes des langages de programmation INF 321. Eric Goubault

INITIATION A LA PROGRAMMATION

Le Langage C Licence Professionnelle Qualité Logiciel Pr. Mouad BEN MAMOUN ben_mamoun@fsr.ac.ma Année universitaire 2011/2012

Déroulement. Evaluation. Préambule. Définition. Définition. Algorithmes et structures de données 28/09/2009

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Les structures. Chapitre 3

Architecture des Systèmes d Information Architecture des Systèmes d Information

PROJET ALGORITHMIQUE ET PROGRAMMATION II

Programmation linéaire

Transcription:

IN 101 - TD 04 30 septembre 2011 Corrigé Solution 1 : Algorithme glouton pour le rendu de monnaie 1 int main(int argc, char** argv) { 2 int s[9] = {500, 200, 100, 50, 20, 10, 5, 2, 1}; 3 int total,i; 4 int first = 1; 5 if (argc > 1) { 6 total = atoi(argv[1]); 7 } else { 8 printf("entrez la somme à atteindre en argument.\n"); 9 return 1; 10 } 11 i=0; 12 while ((total!= 0) && (i < 9)) { 13 if (total < s[i]) { 14 i++; 15 } else { 16 if (first) { 17 printf("%d = %d", total, s[i]); 18 first = 0; 19 } else { 20 printf(" + %d",s[i]); 21 } 22 total -= s[i]; 23 } 24 } 25 if (total!= 0) { 26 printf(" +...\nechec du rendu avec l algorithme glouton.\n"); 27 } else { 28 printf("\nrendu réussi!\n"); 29 } 30 return 0; 31 } Solution 2 : Calcul de coefficients binomiaux 2.a ] Code des fonctions factoriel et binom1 1 int factoriel(int n) { 2 int i, res; 3 res = 1; 4 for (i=2; i<n+1; i++) { 5 res *= i; 7 return res; 1

8 } 9 int binom1(int n, int p) { 10 return factoriel(n)/factoriel(p)/factoriel(n-p); 2.b ] 100! > 2 32, donc 100! ne tient pas sur un mot machine et la fonction factoriel retourne donc les 32 bits de poids faible de l écriture binaire de 100!. Or 100! contient beaucoup de fois le facteur 2, suffisamment pour être multiple de 2 32. Du coup factoriel(100) retourne 0, et factoriel(97) aussi. On a donc une division par 0... 2.c ] Code de la fonction binom2 1 int binom2(int n, int p) { 2 if ((p==0) (n==p)) { 3 return 1; 4 } else { 5 return binom2(n-1,p-1) + binom2(n-1,p); 7 } 2.d ] La fonction binom2 a une complexité égale à la valeur qu elle retourne : le résultat est calculé en faisant une somme de 1. Les grands coefficients binomiaux sont donc longs à calculer car certains calculs sont refaits beaucoup de fois. 2.e ] Code de la fonction binom3 et le main qui va avec 1 int tab[101][101]; 2 int binom3(int n, int p) { 3 if (tab[n][p] == 0) { 4 if ((p==0) (n==p)) { 5 tab[n][p] = 1; else { 7 tab[n][p] = binom3(n-1,p-1) + binom3(n-1,p); 8 } 9 } 10 return tab[n][p]; 12 int main() { 13 int i,j; 14 for (i=0; i<101; i++) { 15 for (j=0; j<101; j++) { 16 tab[i][j] = 0; 17 } 18 } 19 printf("%d\n",binom3(100,6)); 20 return 0; 21 } Cette fonction va calculer une et une seule fois tous les coefficients binomiaux ( i j) pour j [0; p] et i [j; n p + j]. On calcule donc une sorte de parallélogramme dont chaque coefficient se calcule en O(1). La complexité totale est donc O(np). 2

2.f ] Code des fonctions gcd (calcul du pgcd de deux entiers) et binom4 1 int gcd(int a, int b) { 2 if (b == 0) { 3 return a; 4 } else { 5 return gcd(b, a%b); 7 } 8 9 int binom4(int n, int p) { 10 int res, i,a; 11 if ((n-p) < p) { 12 return binom4(n,n-p); 13 } 14 res = 1; 15 for (i=0; i<p; i++) { 16 a = gcd(n-i,i+1); 17 res /= (i+1)/a; 18 res *= (n-i)/a; 19 } 20 return res; 21 } Solution 3 : Exponentiation binaire 3.a ] L algorithme naïf permettant de calculer a b effectue (b 1) multiplications successives par a. Sa complexité est donc Θ(b) multiplications, si on considère une multiplication entre deux entiers comme une opération élémentaire. Complexité en Opérations Binaires On peut aussi s intéresse à la complexité en termes d opérations bit à bit (aussi appelées opérations binaires). On voit que la complexité de la multiplication de x par y est en Θ(log(x) log(y)) (par exemple en utilisant l algorithme que l on utilise quand on pose une multiplication à la main). La complexité de l algorithme naïf en termes d opérations binaires est donc : Θ(log(a) log(a) + log(a 2 log(a) +... + log(a b 1 ) log(a)) ( ) b 1 = Θ log(a) 2 i ( i=1 ) = Θ log(a) 2 b(b 1) 2 = Θ ( log(a) 2 b 2). 3.b ] Afin de décomposer un entier b en base 2, on peut commencer par calculer le bit de poids faible b 0. Si b 0 = 0, alors b est pair et si b 0 = 1, b est impair. Par conséquent, b 0 est le reste de la division euclidienne de b par 2. Le même raisonnement appliqué à b 2 va permettre de calculer b 1 et ainsi de suite. On obtient l algorithme suivant : 3

1 void base2(int b) { 2 while (b > 0) { 3 /* la parité de b est son "et" bit à bit avec 1 */ 4 printf("%d\n", b&1); 5 /* la division par 2 est un décalage à droite de 1 bit */ 6 b = b >> 1; 7 } 8 } En C, les opérations binaires sont très simples et rapides (car les machines travaillent en binaire). Si on voulait écrire une décomposition dans une autre base il faudrait utiliser les opérations modulo et diviser à la place du et et du décalage. Le calcul de la complexité de cet algorithme est très simple : il suffit de calculer le nombre de fois que la boucle while est répétée. À chaque étape on fait un décalage à droite (une division par deux), donc la complexité correspond exactement au nombre de bits nécessaire pour écrire b en base 2, c est-à-dire log 2 (b) + 1. La complexité de l algorithme est donc Θ(log(b)). ( k ) 3.c ] On utilise l équation a b = a i=0 b i 2 i = k i=0 ( a (2 i ) )b i. On va donc mettre en table tous les a (2i) et multiplier ceux pour lesquels b i vaut 1. On obtient l algorithme suivant (on suppose que k est connu et que b < 2 k ) : 1 int binary_exp(int a, int b) { 2 int tab[k]; 3 int i,res; 4 /* on initialise la table */ 5 tab[0] = a; 6 for (i=1; i<k; i++) { 7 tab[i] = tab[i-1]*tab[i-1]; 8 } 9 /* on utilise la table pour le calcul */ 10 res = 1; 11 for (i=0; i<k; i++) 12 if ((b & (1<<i))!= 0) { 13 res = res*tab[i]; 14 } 15 } 16 return res; 17 } Cet algorithme commence par calculer les tab[i] = a (2i) avant de multiplier ceux pour lesquels le bit associé b i vaut 1. La complexité en fonction de k est facile à calculer. En effet, la première boucle effectue k élévations au carré de nombres entiers, et la seconde au plus k multiplications entières ; k étant de l ordre de log(b), on obtient donc Θ(log(b)) multiplications entières. De plus, la première étape ne dépendant que de la taille de l exposant, cette complexité est donc valable que ce soit en moyenne ou dans le cas le pire. Concernant la complexité spatiale, il est nécessaire de stocker Θ(log(b)) entiers. 3.d ] Il est facile d éviter le stockage des tab[i] en utilisant les valeurs au fur et à mesure de leur calcul dans la fonction précédente. Il est également possible d intégrer directement la 4

décomposition en base 2, un peu comme dans la version récursive du TD03, mais en itératif. Cela donne le code suivant : 1 int binary_exp2(int a, int b) { 2 int res = 1; 3 while (b > 0) { 4 if (b & 1) { 5 res = res*a; 7 a = a*a; 8 b = b >> 1; 9 } 10 return res; Cet algorithme a toujours la même complexité de Θ(log(b)) multiplications, mais a une complexité spatiale de Θ(1) entiers. Complexité en Opérations Binaires Si on regarde le nombre d opérations binaires tout n est pourtant pas si rose... En effet, le coût de la dernière élévation au carré est le coût d une multiplication de deux entier de b 2 log 2(a) bits, soit Θ(b 2 log(a) 2 ). Au final, même si on ne fait plus que log(b) multiplications au lieu de b, la complexité binaire n est pas meilleure que pour l algorithme naïf. L exponentiation binaire est donc surtout intéressante quand le coût d une multiplication est constant tout au long de l algorithme : c est ce qu il se passe en cryptographie... Solution 4 : Application à la cryptographie 4.a ] L algorithme précédent s adapte très simplement en effectuant des réductions modulaires dès que possible (et surtout pas à la fin du calcul uniquement). 1 int modular_exp(int m, int e, int n) { 2 int c = 1; 3 while (e > 0) { 4 if (e & 1) { 5 c = c*m % n; 7 m = m*m % n; 8 e = e >> 1; 9 } 10 return c; 4.b ] Avec des exposants de 1024 bits, on effectue 1024 élévations au carré et de l ordre de 512 multiplications en moyenne (selon le nombre de bits valant 1 dans l exposant). Il ne s agit bien sûr plus ici d opérations sur des int (limités à 32 ou 64 bits), mais d opérations plus coûteuses sur des grands entiers. Un chiffrement nécessite donc de l ordre de 1500 multiplications modulaires, ce qui est important, mais réalisable sur une carte à puce, par exemple. Notons que pour de telles tailles l algorithme naïf nécessite de l ordre de 2 1024 multiplications... 5

4.c ] On a e = 65537 = 2 16 + 1. L avantage de cet exposant est de ne nécessiter que deux multiplications et non 8 comme c est le cas en moyenne. Il faut donc 16 élévations au carré plus deux multiplications soit 18 opérations modulaires, au lieu de 24 en moyenne. De plus 65537 est un nombre premier. 6