introduction à l'informatique - cours polytechnique (2011)

Upload: titifanfan

Post on 06-Apr-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    1/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    2/252

    2

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    3/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    4/252

    2

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    5/252

    Table des matieres

    I Introduction a la programmation 11

    1 Les premiers pas en Java 131.1 Le premier programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

    1.1.1 Ecriture et execution . . . . . . . . . . . . . . . . . . . . . . . . . 131.1.2 Analyse de ce programme . . . . . . . . . . . . . . . . . . . . . . 14

    1.2 Faire des calculs simples . . . . . . . . . . . . . . . . . . . . . . . . . . . 151.3 Types primitifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151.4 Declaration des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.5 Affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.6 Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    1.6.1 Regles devaluation . . . . . . . . . . . . . . . . . . . . . . . . . . 181.6.2 Incrementation et decrementation . . . . . . . . . . . . . . . . . 18

    1.7 Methodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

    2 Suite dinstructions 212.1 Expressions booleennes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

    2.1.1 Operateurs de comparaisons . . . . . . . . . . . . . . . . . . . . . 212.1.2 Connecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

    2.2 Instructions conditionnelles . . . . . . . . . . . . . . . . . . . . . . . . . 222.2.1 If-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.2.2 Forme compacte . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2.3 Aiguillage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

    2.3 Iterations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.3.1 Boucles pour (for) . . . . . . . . . . . . . . . . . . . . . . . . . 242.3.2 Iterations tant que . . . . . . . . . . . . . . . . . . . . . . . . . . 262.3.3 Iterations repeter tant que . . . . . . . . . . . . . . . . . . . . . . 27

    2.4 Terminaison des programmes . . . . . . . . . . . . . . . . . . . . . . . . 282.5 Instructions de rupture de controle . . . . . . . . . . . . . . . . . . . . . 282.6 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

    2.6.1 Methode de Newton . . . . . . . . . . . . . . . . . . . . . . . . . 28

    3 Methodes : theorie et pratique 313.1 Pourquoi ecrire des methodes . . . . . . . . . . . . . . . . . . . . . . . . 313.2 Comment ecrire des methodes . . . . . . . . . . . . . . . . . . . . . . . . 32

    3.2.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323.2.2 Le type special void . . . . . . . . . . . . . . . . . . . . . . . . . 333.2.3 La surcharge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    3

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    6/252

    4 TABLE DES MATIERES

    3.3 Visibilite des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    3.4 Quelques conseils pour ecrire un (petit) programme . . . . . . . . . . . . 36

    4 Tableaux 394.1 Declaration, construction, initialisation . . . . . . . . . . . . . . . . . . . 394.2 Representation en memoire et consequences . . . . . . . . . . . . . . . . 404.3 Tableaux a plusieurs dimensions, matrices . . . . . . . . . . . . . . . . . 434.4 Les tableaux comme arguments de fonction . . . . . . . . . . . . . . . . 444.5 Exemples dutilisation des tableaux . . . . . . . . . . . . . . . . . . . . . 45

    4.5.1 Algorithmique des tableaux . . . . . . . . . . . . . . . . . . . . . 454.5.2 Un peu dalgebre lineaire . . . . . . . . . . . . . . . . . . . . . . 474.5.3 Le crible dEratosthene . . . . . . . . . . . . . . . . . . . . . . . 494.5.4 Jouons a la bataille rangee . . . . . . . . . . . . . . . . . . . . . 504.5.5 Pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

    5 Classes, objets 575.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

    5.1.1 Declaration et creation . . . . . . . . . . . . . . . . . . . . . . . . 575.1.2 Objet et reference . . . . . . . . . . . . . . . . . . . . . . . . . . 585.1.3 Constructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

    5.2 Autres composants dune classe . . . . . . . . . . . . . . . . . . . . . . . 605.2.1 Methodes de classe et methodes dobjet . . . . . . . . . . . . . . 605.2.2 Passage par reference . . . . . . . . . . . . . . . . . . . . . . . . 615.2.3 Variables de classe . . . . . . . . . . . . . . . . . . . . . . . . . . 615.2.4 Utiliser plusieurs classes . . . . . . . . . . . . . . . . . . . . . . . 62

    5.3 Autre exemple de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

    5.4 Public et private . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635.5 Un exemple de classe predefinie : la classe String . . . . . . . . . . . . 63

    5.5.1 Proprietes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635.5.2 Arguments de main . . . . . . . . . . . . . . . . . . . . . . . . . 65

    5.6 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

    6 Recursivite 676.1 Premiers exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676.2 Des exemples moins elementaires . . . . . . . . . . . . . . . . . . . . . . 69

    6.2.1 Ecriture binaire des entiers . . . . . . . . . . . . . . . . . . . . . 696.2.2 Les tours de Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . 71

    6.3 Un piege subtil : les nombres de Fibonacci . . . . . . . . . . . . . . . . . 72

    6.4 Fonctions mutuellement recursives . . . . . . . . . . . . . . . . . . . . . 746.4.1 Pair et impair sont dans un bateau . . . . . . . . . . . . . . . . . 756.4.2 Developpement du sinus et du cosinus . . . . . . . . . . . . . . . 75

    6.5 Le probleme de la terminaison . . . . . . . . . . . . . . . . . . . . . . . . 76

    7 Introduction a la complexite des algorithmes 797.1 Complexite des algorithmes . . . . . . . . . . . . . . . . . . . . . . . . . 797.2 Calculs elementaires de complexite . . . . . . . . . . . . . . . . . . . . . 807.3 Quelques algorithmes sur les tableaux . . . . . . . . . . . . . . . . . . . 81

    7.3.1 Recherche du plus petit element . . . . . . . . . . . . . . . . . . 817.3.2 Recherche dichotomique . . . . . . . . . . . . . . . . . . . . . . . 81

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    7/252

    TABLE DES MATIERES 5

    7.3.3 Recherche simultanee du maximum et du minimum . . . . . . . 82

    7.4 Diviser pour resoudre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847.4.1 Recherche dune racine par dichotomie . . . . . . . . . . . . . . . 847.4.2 Exponentielle binaire . . . . . . . . . . . . . . . . . . . . . . . . . 85

    II Structures de donnees classiques 87

    8 Listes chanees 898.1 Operations elementaires sur les listes . . . . . . . . . . . . . . . . . . . . 90

    8.1.1 Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908.1.2 Affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 918.1.3 Longueur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928.1.4 Le i-eme element . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

    8.1.5 Ajouter des elements en queue de liste . . . . . . . . . . . . . . . 938.1.6 Copier une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948.1.7 Suppression de la premiere occurrence . . . . . . . . . . . . . . . 95

    8.2 Interlude : tableau ou liste ? . . . . . . . . . . . . . . . . . . . . . . . . . 968.3 Partages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

    8.3.1 Insertion dans une liste triee . . . . . . . . . . . . . . . . . . . . 978.3.2 Inverser les fleches . . . . . . . . . . . . . . . . . . . . . . . . . . 97

    8.4 Exemple de gestion de la memoire au plus juste . . . . . . . . . . . . . . 98

    9 Arbres 1019.1 Arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

    9.1.1 Representation en machine . . . . . . . . . . . . . . . . . . . . . 101

    9.1.2 Complexite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1029.1.3 Les trois parcours classiques . . . . . . . . . . . . . . . . . . . . . 1029.2 Arbres generaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

    9.2.1 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1039.2.2 Representation en machine . . . . . . . . . . . . . . . . . . . . . 104

    9.3 Exemples dutilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1049.3.1 Expressions arithmetiques . . . . . . . . . . . . . . . . . . . . . . 1049.3.2 Arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . 1089.3.3 Les tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

    10 Graphes 11710.1 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11710.2 Representation en machine . . . . . . . . . . . . . . . . . . . . . . . . . 119

    10.2.1 Representation par une matrice . . . . . . . . . . . . . . . . . . . 11910.2.2 Representation par un tableau de listes . . . . . . . . . . . . . . 120

    10.3 Recherche des composantes connexes . . . . . . . . . . . . . . . . . . . . 12110.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

    11 Ranger linformation. . . pour la retrouver 12711.1 Recherche en table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

    11.1.1 Recherche lineaire . . . . . . . . . . . . . . . . . . . . . . . . . . 12711.1.2 Recherche dichotomique . . . . . . . . . . . . . . . . . . . . . . . 12811.1.3 Utilisation dindex . . . . . . . . . . . . . . . . . . . . . . . . . . 129

    11.2 Trier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    8/252

    6 TABLE DES MATIERES

    11.2.1 Tris elementaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

    11.2.2 Un tri rapide : le tri par fusion . . . . . . . . . . . . . . . . . . . 13311.3 Hachage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

    III Introduction au genie logiciel 141

    12 Comment ecrire un programme 14312.1 Pourquoi du genie logiciel ? . . . . . . . . . . . . . . . . . . . . . . . . . 14312.2 Principes generaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

    12.2.1 La chane de production logicielle . . . . . . . . . . . . . . . . . . 14312.2.2 Architecture detaillee . . . . . . . . . . . . . . . . . . . . . . . . 14512.2.3 Aspects organisationnels . . . . . . . . . . . . . . . . . . . . . . . 145

    12.2.4 En guise de conclusion provisoire. . . . . . . . . . . . . . . . . . . 15012.3 Un exemple detaille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

    12.3.1 Le probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15012.3.2 Architecture du programme . . . . . . . . . . . . . . . . . . . . . 15012.3.3 Programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15112.3.4 Tests exhaustifs du programme . . . . . . . . . . . . . . . . . . . 15812.3.5 Est-ce tout ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15912.3.6 Calendrier et formule de Zeller . . . . . . . . . . . . . . . . . . . 159

    13 Introduction au genie logiciel en Java 16313.1 Modularite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16313.2 Les interfaces de Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

    13.2.1 Piles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16413.2.2 Files dattente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16613.2.3 Les generiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

    13.3 Retour au calcul du jour de la semaine . . . . . . . . . . . . . . . . . . . 168

    14 Modelisation de linformation 17314.1 Modelisation et realisation . . . . . . . . . . . . . . . . . . . . . . . . . . 173

    14.1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17314.1.2 Exemple : les donnees . . . . . . . . . . . . . . . . . . . . . . . . 174

    14.2 Conteneurs, collections et ensembles . . . . . . . . . . . . . . . . . . . . 17414.2.1 Collections sequentielles . . . . . . . . . . . . . . . . . . . . . . . 17514.2.2 Collections ordonnees . . . . . . . . . . . . . . . . . . . . . . . . 175

    14.3 Associations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17714.4 Information hierarchique . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

    14.4.1 Exemple : arbre genealogique . . . . . . . . . . . . . . . . . . . . 17714.4.2 Autres exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

    14.5 Quand les relations sont elles-memes des donnees . . . . . . . . . . . . . 17814.5.1 Un exemple : un reseau social . . . . . . . . . . . . . . . . . . . . 178

    14.6 Automates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18414.6.1 Lexemple de la machine a cafe . . . . . . . . . . . . . . . . . . . 18414.6.2 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18414.6.3 Representations dautomate deterministe . . . . . . . . . . . . . 185

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    9/252

    TABLE DES MATIERES 7

    IV Problematiques classiques en informatique 187

    15 Recherche exhaustive 18915.1 Rechercher dans du texte . . . . . . . . . . . . . . . . . . . . . . . . . . 18915.2 Le probleme du sac-a-dos . . . . . . . . . . . . . . . . . . . . . . . . . . 194

    15.2.1 Premieres solutions . . . . . . . . . . . . . . . . . . . . . . . . . . 19415.2.2 Deuxieme approche . . . . . . . . . . . . . . . . . . . . . . . . . 19515.2.3 Code de Gray* . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19815.2.4 Retour arriere (backtrack) . . . . . . . . . . . . . . . . . . . . . . 203

    15.3 Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20515.3.1 Fabrication des permutations . . . . . . . . . . . . . . . . . . . . 205

    15.3.2 Enumeration des permutations . . . . . . . . . . . . . . . . . . . 20615.4 Les n reines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

    15.4.1 Prelude : les n tours . . . . . . . . . . . . . . . . . . . . . . . . . 20715.4.2 Des reines sur un echiquier . . . . . . . . . . . . . . . . . . . . . 20715.5 Les ordinateurs jouent aux echecs . . . . . . . . . . . . . . . . . . . . . . 209

    15.5.1 Principes des programmes de jeu . . . . . . . . . . . . . . . . . . 20915.5.2 Retour aux echecs . . . . . . . . . . . . . . . . . . . . . . . . . . 210

    16 Polynomes et transformee de Fourier 21316.1 La classe Polynome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213

    16.1.1 Definition de la classe . . . . . . . . . . . . . . . . . . . . . . . . 21316.1.2 Creation, affichage . . . . . . . . . . . . . . . . . . . . . . . . . . 21416.1.3 Predicats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21416.1.4 Premiers tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

    16.2 Premieres fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

    16.2.1 Derivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21716.2.2 Evaluation ; schema de Horner . . . . . . . . . . . . . . . . . . . 217

    16.3 Addition, soustraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21816.4 Deux algorithmes de multiplication . . . . . . . . . . . . . . . . . . . . . 220

    16.4.1 Multiplication nave . . . . . . . . . . . . . . . . . . . . . . . . . 22016.4.2 Lalgorithme de Karatsuba . . . . . . . . . . . . . . . . . . . . . 220

    16.5 Multiplication a laide de la transformee de Fourier* . . . . . . . . . . . 22616.5.1 Transformee de Fourier . . . . . . . . . . . . . . . . . . . . . . . 22616.5.2 Application a la multiplication de polynomes . . . . . . . . . . . 22716.5.3 Transformee rapide . . . . . . . . . . . . . . . . . . . . . . . . . . 228

    V Annexes 231

    A Complements 233A.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233A.2 La classe MacLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

    A.2.1 Fonctions elementaires . . . . . . . . . . . . . . . . . . . . . . . . 234A.2.2 Rectangles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235A.2.3 La classe Maclib . . . . . . . . . . . . . . . . . . . . . . . . . . 236A.2.4 Jeu de balle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

    A.3 La classe TC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238A.3.1 Fonctionnalites, exemples . . . . . . . . . . . . . . . . . . . . . . 238

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    10/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    11/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    12/252

    10 TABLE DES MATIERES

    Remerciements pour la version 3.0 :

    P. Chassignet ma aide a rediger le nouveau chapitre 14, quil en soit sincerement re-mercie. Merci a E. Duris pour sa relecture attentive de la partie genie logicielle (nouvelleelle aussi). Enfin, rien nest possible sans des relecteurs : L. Castelli Aleardi, Y. Ponty,S. Redon, O. Serre.

    Remerciements pour les versions 20012010 :

    G. Guillerm ma aide pour le chapitre Internet, J. Marchand pour le courrierelectronique, T. Besancon pour NFS. Quils en soient remercie ici, ainsi que E. Thomepour ses coups de main, V. Menissier-Morain pour son aide. Je remercie egalement lesrelecteurs de la presente version : T. Clausen, E. Duris, C. Gwiggner, J.-R. Reinhard ;E. Waller, ce dernier etant egalement le beta-testeur de mes transparents damphis, ce

    qui les a rendus dautant plus justes.Remerciements pour la version initiale (2000) : Je remercie chaleureusement

    Jean-Jacques Levy et Robert Cori pour mavoir permis de reutiliser des parties deleurs polycopies anciens ou nouveaux.

    Le polycopie a ete ecrit avec LATEX, il est consultable a ladresse :http://www.enseignement.polytechnique.fr/informatique/INF311

    Les erreurs seront corrigees des quelles me seront signalees et les mises a jour eventuellesseront effectuees sur la version mise sur le web.

    Polycopie, version 3.0, 11 avril 2011

    http://www.enseignement.polytechnique.fr/informatique/INF311http://www.enseignement.polytechnique.fr/informatique/INF311
  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    13/252

    Premiere partie

    Introduction a la programmation

    11

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    14/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    15/252

    Chapitre 1

    Les premiers pas en Java

    Dans ce chapitre on donne quelques elements simples de la programmation avec lelangage Java : types, variables, affectations, fonctions. Ce sont des traits communs atous les langages de programmation.

    1.1 Le premier programme

    1.1.1 Ecriture et execution

    Commencons par un exemple simple de programme. Cest un classique, il sagitsimplement dafficher Bonjour ! a lecran.

    // Voici mon premier programme

    public class Premier{

    public static void main(String[] args){

    System.out.println("Bonjour !");

    return;

    }

    }

    Pour executer ce programme il faut commencer par le copier dans un fichier. Pourcela on utilise un editeur de texte (par exemple nedit) pour creer un fichier de nomPremier.java (le meme nom que celui qui suit class). Ce fichier doit contenir letexte du programme. Apres avoir tape le texte, on doit le traduire (les informaticiens

    disent compiler) dans un langage que comprend lordinateur. Cette compilation se faita laide de la commande1

    unix% javac Premier.java

    Ceci a pour effet de faire construire par le compilateur un fichier Premier.class,que la machine virtuelle de Java rendra comprehensible pour lordinateur :

    unix% java Premier

    1Une ligne commencant par unix% indique une commande tapee en Unix.

    13

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    16/252

    14 CHAPITRE 1. LES PREMIERS PAS ENJAVA

    On voit safficher :

    Bonjour !

    1.1.2 Analyse de ce programme

    Un langage de programmation est comme un langage humain. Il y a un ensemblede lettres avec lesquelles on forme des mots. Les mots forment des phrases, les phrasesdes paragraphes, ceux-ci forment des chapitres qui rassembles donnent naissance a unlivre. Lalphabet de Java est peu ou prou lalphabet que nous connaissons, avec deslettres, des chiffres, quelques signes de ponctuation. Les mots seront les mots-clefs dulangage (comme class, public, etc.), ou formeront les noms des variables que nousutiliserons plus loin. Les phrases seront pour nous des instructions, les paragraphes des

    fonctions (appelees methodes dans la terminologie des langages a objets). Les chapitresseront les classes, les livres des programmes que nous pourrons executer et utiliser.Le premier chapitre dun livre est lamorce du livre et ne peut generalement etre

    saute. En Java, un programme debute toujours a partir dune methode speciale, appeleemain et dont la syntaxe immuable est :

    public static void main(String[] args)

    Nous verrons plus loin ce que veulent dire les mots magiques public, static et void,args contient quant a lui des arguments quon peut passer au programme. Reprenonsla methode main :

    public static void main(String[] args){

    System.out.println("Bonjour !");

    return;

    }

    Les accolades { et } servent a constituer un bloc dinstructions ; elles doivent en-glober les instructions dune methode, de meme quune paire daccolades doit engloberlensemble des methodes dune classe.

    Notons quen Java les instructions se terminent toutes par un ; (point-virgule).Ainsi, dans la suite le symbole I signifiera soit une instruction (qui se termine doncpar ;) soit une suite dinstructions (chacune finissant par ;) placees entre accolades.

    La methode effectuant le travail est la methode System.out.println qui appar-tient a une classe predefinie, la classe System. En Java, les classes peuvent sappelerles unes les autres, ce qui permet une approche modulaire de la programmation : on

    na pas a recrire tout le temps la meme chose.Notons que nous avons ecrit les instructions de chaque ligne en respectant un

    decalage bien precis (on parle dindentation). La methode System.out.printlnetant executee a linterieur de la methode main, elle est decalee de plusieurs blancs(ici 4) sur la droite. Lindentation permet de bien structurer ses programmes, elle estsystematiquement utilisee partout.

    La derniere instruction presente dans la methode main est linstruction return;que nous comprendrons pour le moment comme voulant dire : rendons la main a luti-lisateur qui nous a lance. Nous en preciserons le sens a la section 1.7.

    La derniere chose a dire sur ce petit programme est quil contient un commentaire,repere par // et se terminant a la fin de la ligne. Les commentaires ne sont utiles

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    17/252

    1.2. FAIRE DES CALCULS SIMPLES 15

    qua des lecteurs (humains) du texte du programme, ils nauront aucun effet sur la

    compilation ou lexecution. Ils sont tres utiles pour comprendre le programme.

    1.2 Faire des calculs simples

    On peut se servir de Java pour realiser les operations dune calculette elementaire :on affecte la valeur dune expression a une variable et on demande ensuite laffichagede la valeur de la variable en question. Bien entendu, un langage de programmationnest pas fait uniquement pour cela, toutefois cela nous donne quelques exemples deprogrammes simples ; nous passerons plus tard a des programmes plus complexes.

    // Voici mon deuxieme programme

    public class PremierCalcul{

    public static void main(String[] args){int a;

    a = 5 * 3;

    System.out.println(a);

    a = 2 8 7 % 7 ;

    System.out.println(a);

    return;

    }

    }

    Dans ce programme on voit apparatre une variable de nom a qui est declaree au

    debut. Comme les valeurs quelle prend sont des entiers elle est dite de type entier. Lemot int2 qui precede le nom de la variable est une declaration de type. Il indique que lavariable est de type entier et ne prendra donc que des valeurs entieres lors de lexecutiondu programme. Par la suite, on lui affecte deux fois une valeur qui est ensuite affichee.Les resultats affiches seront 15 et 0. Dans loperation a % b, le symbole % designeloperation modulo qui est le reste de la division euclidienne de a par b (quand a et bsont positifs).

    Insistons un peu sur la facon dont le programme est execute par lordinateur. Celui-ci lit les instructions du programme une a une en commencant par la methode main, etles traite dans lordre ou elles apparaissent. Il sarrete des quil rencontre linstructionreturn;, qui est generalement la derniere presente dans une methode. Nous revien-drons sur le mode de traitement des instructions quand nous introduirons de nouvellesconstructions (iteration, recursion).

    1.3 Types primitifs

    Un type en programmation precise lensemble des valeurs que peut prendre unevariable ; les operations que lon peut effectuer sur une variable dependent de son type.

    Le type des variables que lon utilise dans un programme Java doit etre declare.Parmi les types possibles, les plus simples sont les types primitifs. Il y a peu de typesprimitifs : les entiers, les reels, les caracteres et les booleens.

    2Une abreviation de langlais integer, le g etant prononce comme un j francais.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    18/252

    16 CHAPITRE 1. LES PREMIERS PAS ENJAVA

    Les principaux types entiers sont int et long, le premier utilise 32 bits (un bit vaut

    0 ou 1, cest un chiffre binaire) pour representer un nombre ; sachant que le premier bitest reserve au signe, un int fait reference a un entier de lintervalle [231, 231 1]. Silors dun calcul, un nombre depasse cette valeur le resulat obtenu nest pas utilisable.Le type long permet davoir des mots de 64 bits (entiers de lintervalle [263, 263 1])et on peut donc travailler sur des entiers plus grands. Il y a aussi les types byte etshort qui permettent dutiliser des mots de 8 et 16 bits. Les operations sur les intsont toutes les operations arithmetiques classiques : les operations de comparaison :egal (==), different de (!=), plus petit () et les operations de calculcomme addition (+), soustraction (-), multiplication (*), division (/), reste (%). Dansce dernier cas, precisons que a/b calcule le quotient de la division euclidienne de a parb et que a % b en calcule le reste. Par suite

    int q = 2/3;

    contient le quotient de la division euclidienne de 2 par 3, cest- a-dire 0.Les types reels (en fait, des nombres dont le developpement binaire est fini) sont

    float et double, le premier se contente dune precision dite simple, le second donnela possibilite dune plus grande precision, on dit que lon a une double precision.

    Les caracteres sont declares par le type char au standard Unicode. Ils sont codessur 16 bits et permettent de representer toutes les langues de la planete (les caractereshabituels des claviers des langues europeennes se codent uniquement sur 8 bits). Lestandard Unicode respecte lordre alphabetique. Ainsi le code de a est inferieur a celuide d, et celui de A a celui de D.

    Le type des booleens est boolean et ses deux valeurs possibles sont true et false.Les operations sont et, ou, et non ; elles se notent respectivement &&, ||, !. Si a et

    b sont deux booleens, le resultat de a & & b est true si et seulement si a et b sont tousdeux egaux a true. Celui de a | | b est true si et seulement si lun de a ou b estegal a true. Enfin !a est true quand a est false et reciproquement. Les booleenssont utilises dans les conditions decrites au chapitre suivant.

    1.4 Declaration des variables

    La declaration du type des variables est obligatoire en Java, mais elle peut se fairea linterieur dune methode et pas necessairement au debut de celle-ci. Une declarationse presente sous la forme dun nom de type suivi soit dun nom de variable, soit dunesuite de noms de variables separes par des virgules. En voici quelques exemples :

    int a, b, c;float x;

    char ch;

    boolean u, v;

    1.5 Affectation

    On a vu quune variable a un nom et un type. Loperation la plus courante sur lesvariables est laffectation dune valeur. Elle secrit :

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    19/252

    1.5. AFFECTATION 17

    double

    T

    float

    T

    long

    T

    int char'

    T

    short

    Tbyte

    Fig. 1.1 Coercions implicites.

    x = E ;

    ou E est une expression qui peut contenir des constantes et des variables. Lors duneaffectation, lexpression E est evaluee et le resultat de son evaluation est affecte a la

    variable x. Lorsque lexpression E contient des variables leur contenu est egal a laderniere valeur qui leur a ete affectee.Par exemple, laffectation

    x = x + a;

    consiste a augmenter la valeur de x de la quantite a. Par exemple

    x = 12;

    x = x + 5;

    donnera a x la valeur 17.Pour une affectation

    x = E ;

    le type de lexpression E et celui de la variable x doivent etre compatibles. Dans un trespetit nombre de cas cette exigence nest pas appliquee, il sagit alors des conversionsimplicites de types. Les conversions implicites suivent la figure 1.1. Pour toute operation,on convertit toujours au plus petit commun majorant des types des operandes. Desconversions explicites sont aussi possibles, et recommandees dans le doute. On peut lesfaire par loperation dite de coercion (cast) suivante

    x = (nom-type) E;

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    20/252

    18 CHAPITRE 1. LES PREMIERS PAS ENJAVA

    Lexpression E est alors convertie dans le type indique entre parentheses devant lexpres-

    sion. Loperateur = daffectation est un operateur comme les autres dans les expressions.Il subit donc les memes lois de conversion. Toutefois, il se distingue des autres operationspar le type du resultat. Pour un operateur ordinaire, le type du resultat est le typecommun obtenu par conversion des deux operandes. Pour une affectation, le type duresultat est le type de lexpression a gauche de laffectation. Il faut donc faire uneconversion explicite sur lexpression de droite pour que le resultat soit coherent avec letype de lexpression de gauche. Cest le cas de lexemple

    int x = (int)12.7;

    ou le flottant 12.7 sera converti en entier, soit 12.

    1.6 OperationsLa plupart des operations arithmetiques courantes sont disponibles en Java, ainsi

    que les operations sur les booleens (voir chapitre suivant). Ces operations ont un ordrede priorite correspondant aux conventions usuelles.

    1.6.1 Regles devaluation

    Les principales operations sont +,-,*,/, % pour laddition, soustraction, multi-plication, division et le reste de la division (modulo). Il y a des regles de priorite, ainsiloperation de multiplication a une plus grande priorite que laddition, cela signifie queles multiplications sont faites avant les additions. La presence de parentheses permetde mieux controler le resultat. Par exemple 3 + 5 * 6 est evalue a 33 ; par contre

    (3 + 5) * 6 est evalue a 48. Une expression a toujours un type et le resultat de sonevaluation est une valeur ayant ce type.

    On utilise souvent des raccourcis pour les instructions du type

    x = x + a;

    quon a tendance a ecrire de facon equivalente, mais plus compacte :

    x + = a ;

    1.6.2 Incrementation et decrementation

    Soit i une variable de type int. On peut lincrementer, cest-a-dire lui additionner

    1 a laide de linstruction :i = i + 1;

    Cest une instruction tellement frequente (particulierement dans lecriture des boucles,cf. chapitre suivant), quil existe deux raccourcis : i++ et ++i. Dans le premier cas, ilsagit dune post-incrementation, dans le second dune pre-incrementation. Expliquonsla difference entre les deux. Le code

    i = 2 ;

    j = i++;

    donne la valeur 3 a i et 2 a j, car le code est equivalent a :

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    21/252

    1.7. METHODES 19

    i = 2 ;

    j = i ;i = i + 1;

    on incremente en tout dernier lieu. Par contre :

    i = 2 ;

    j = ++i;

    est equivalent quant a lui a :

    i = 2 ;

    i = i + 1;

    j = i ;

    et donc on termine avec i=3 et j=3.Il existe aussi des raccourcis pour la decrementation : i = i-1 peut secrire aussi

    i-- ou --i avec les memes regles que pour ++.

    1.7 Methodes

    Le programme suivant, qui calcule la circonference dun cercle en methode de sonrayon, contient deux methodes, main, que nous avons deja rencontree, ainsi quunenouvelle methode, circonference, qui prend en argument un reel r et retourne lavaleur de la circonference, qui est aussi un reel :

    // Calcul de circonference

    public class Cercle{

    static float p i = (float)Math.PI;

    public static float circonference(float r){

    return 2. * pi * r;

    }

    public static void main(String[] args){

    float c = circonference(1.5);

    System.out.print("Circonference: ");

    System.out.println(c);

    return;

    }

    }

    De facon generale, une methode peut avoir plusieurs arguments, qui peuvent etre detypes differents et retourne une valeur (dont le type doit etre aussi precise). Certainesmethodes ne retournent aucune valeur. Elles sont alors declarees de type void. Cest lecas particulier de la methode main de notre exemple. Pour bien indiquer dans ce cas lepoint ou la methode renvoie la main a lappelant, nous utiliserons souvent un return;explicite, qui est en fait optionnel. Il y a aussi des cas o u il ny a pas de parametreslorsque la methode effectue toujours les memes operations sur les memes valeurs.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    22/252

    20 CHAPITRE 1. LES PREMIERS PAS ENJAVA

    Len-tete dune methode decrit le type du resultat dabord puis les types des pa-

    rametres qui figurent entre parentheses.Les programmes que lon a vu ci-dessus contiennent une seule methode appeleemain. Lorsquon effectue la commande java Nom-classe, cest la methode main setrouvant dans cette classe qui est executee en premier.

    Une methode peut appeler une autre methode ou etre appelee par une autre me-thode, il faut alors donner des arguments aux parametres dappel.

    Ce programme contient deux methodes dans une meme classe, la premiere methodea un parametre r et utilise la constante PI qui se trouve dans la classe Math, cetteconstante est de type double il faut donc la convertir au type float pour affecter savaleur a un nombre de ce type.

    Le resultat est fourni, on dit plutot retourne a lappelant par return. Lappelantest ici la methode main qui apres avoir effectue lappel, affiche le resultat.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    23/252

    Chapitre 2

    Suite dinstructions

    Dans ce chapitre on sinteresse a deux types dinstructions : les instructions condi-tionnelles, qui permettent deffectuer une operation dans le cas ou une certaine conditionest satisfaite et les iterations qui donnent la possibilite de repeter plusieurs fois la memeinstruction (pour des valeurs differentes des variables !).

    2.1 Expressions booleennes

    Le point commun aux diverses instructions decrites ci-dessous est quelles utilisentdes expressions booleennes, cest-a-dire dont levaluation donne lune des deux valeurstrue ou false.

    2.1.1 Operateurs de comparaisons

    Les operateurs booleens les plus simples sont

    == != < > =

    egal different plus petit plus grand plus petit ou egal plus grand ou egal

    Le resultat dune comparaison sur des variables de type primitif :

    a = = b

    est egal a true si levaluation de la variable a et de la variable b donnent le memeresultat, il est egal a false sinon. Par exemple, (5-2) == 3 a pour valeur true,mais 22/7 == 3.14159 a pour valeur false.

    Remarque : Attention a ne pas ecrire a = b qui est une affectation et pas une com-paraison.

    Loperateur != est loppose de ==, ainsi a != b prend la valeur true si leva-luation de a et de b donne des valeurs differentes.

    Les operateurs de comparaison , = ont des significations evidentes lorsquilsagit de comparer des nombres. Noter quils peuvent aussi servir a comparer des ca-racteres ; pour les caracteres latins courants cest lordre alphabetique qui est exprime.

    21

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    24/252

    22 CHAPITRE 2. SUITE DINSTRUCTIONS

    2.1.2 Connecteurs

    On peut construire des expressions booleennes comportant plusieurs comparateursen utilisant les connecteurs &&, qui signifie et, || qui signifie ou et ! qui signifie non.

    Ainsi C1 && C2 est evalue a true si et seulement si les deux expressions C1 etC2 le sont. De meme C1 || C2 est evalue a true si lune deux expressions C1 ou C2lest.

    Par exemple

    !( ((a

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    25/252

    2.2. INSTRUCTIONS CONDITIONNELLES 23

    permettent de calculer le signe de a et de le mettre dans b.

    La partie else I2 est facultative, elle est omise si la suite I2 est vide cest a diresil ny a aucune instruction a executer dans le cas ou C est evaluee a false.

    On peut avoir plusieurs branches separees par des else if comme par exempledans :

    if(a == 0 ) x = 1;

    else if (a < 0) x = 2;

    else if (a > -5) x = 3;

    else x = 4 ;

    qui donne 4 valeurs possibles pour x suivant les valeurs de a.

    2.2.2 Forme compacte

    Il existe une forme compacte de linstruction conditionnelle utilisee comme unoperateur ternaire (a trois operandes) dont le premier est un booleen et les deux autressont de type primitif. Cet operateur secrit C ? E 1 : E 2. Elle est utilisee quand unif else parat lourd, par exemple pour le calcul dune valeur absolue :

    x = ( a > b ) ? a - b : b - a ;

    2.2.3 Aiguillage

    Quand diverses instructions sont a realiser suivant les valeurs que prend une va-riable, plusieurs if imbriques deviennent lourds a mettre en uvre, on peut les rem-placer avantageusement par un aiguillage switch. Un tel aiguillage a la forme suivantedans laquelle x est une variable dun type primitif (entier, caractere ou booleen, pasreel) et a,b,c sont des constantes representant des valeurs que peut prendre cette va-riable. Lors de lexecution les valeurs apres chaque case sont testees lune apres lautre

    jusqua obtenir celle prise par x ou arriver a default, ensuite toutes les instructionssont executees en sequence jusqua la fin. Par exemple dans linstruction :

    switch(x){

    case a : I1

    case b : I2

    case c : I3

    default : I4

    }

    Si la variable x est evaluee a b alors toutes les suites dinstructions I2, I3, I4seront executees, a moins que lune dentre elles ne contienne un break qui interromptcette suite. Si la variable est evaluee a une valeur differente de a,b,c cest la suite I4qui est executee.

    Pour sortir de linstruction avant la fin, il faut passer par une instruction break .Le programme suivant est un exemple typique dutilisation :

    switch(c){

    case s:

    System.out.println("samedi est un jour de week-end");

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    26/252

    24 CHAPITRE 2. SUITE DINSTRUCTIONS

    break;

    case d:System.out.println("dimanche est un jour de week-end");

    break;

    default:

    System.out.print(c);

    System.out.println(" nest pas un jour de week-end");

    break;

    }

    permet dafficher les jours du week-end. Noter labsence daccolades dans les differentscas. Si lon ecrit plutot de facon erronee en oubliant les break :

    switch(c){

    case s:System.out.println("samedi est un jour de week-end");

    case d:

    System.out.println("dimanche est un jour de week-end");

    default:

    System.out.print(c);

    System.out.println(" nest pas un jour de week-end");

    break;

    }

    on obtiendra, dans le cas ou c sevalue a s :

    samedi est un jour de week-enddimanche est un jour de week-end

    s nest pas un jour de week-end

    2.3 Iterations

    Une iteration permet de repeter plusieurs fois la meme suite dinstructions. Elle estutilisee pour evaluer une somme, une suite recurrente, le calcul dun plus grand commundiviseur par exemple. Elle sert aussi pour effectuer des traitements plus informatiquescomme la lecture dun fichier. On a lhabitude de distinguer les boucles pour (for)des boucles tant-que (while). Les premieres sont utilisees lorsquon connat, lors de

    lecriture du programme, le nombre de fois ou les operations doivent etre iterees, lessecondes servent a exprimer des tests darret dont le resultat nest pas previsible alavance. Par exemple, le calcul dune somme de valeurs pour i variant de 1 a n releveplutot de la categorie boucle-pour, celui du calcul dun plus grand commun diviseurpar lalgorithme dEuclide releve plutot dune boucle tant-que.

    2.3.1 Boucles pour (for)

    Literation de type boucle-pour en Java est un peu deroutante pour ceux qui ladecouvrent pour la premiere fois. Lexemple le plus courant est celui ou on execute unesuite doperations pour i variant de 1 a n, comme dans :

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    27/252

    2.3. ITERATIONS 25

    int i;

    for(i = 1; i

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    28/252

    26 CHAPITRE 2. SUITE DINSTRUCTIONS

    Noter que les instructions Init ou Inc de la forme generale (ou meme les deux)

    peuvent etre vides. Il ny a alors pas dinitialisation ou pas dincrementation ; lini-tialisation peut, dans ce cas, figurer avant le for et lincrementation a linterieur deI.

    Insistons sur le fait que la boucle

    for(int i = 1; i

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    29/252

    2.3. ITERATIONS 27

    double s = 0.0;

    for(int i = 1; i

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    30/252

    28 CHAPITRE 2. SUITE DINSTRUCTIONS

    que lon appelle par :

    unix% java Syracuse 101

    Linstruction magique Integer.parseInt(args[0]); permet de recuperer la va-leur de lentier 101 passe sur la ligne de commande.

    2.4 Terminaison des programmes

    Le programme que nous venons de voir peut etre considere comme etrange, voiredangereux. En effet, si la conjecture est fausse, alors le programme ne va jamaissarreter, on dit quil ne termine pas. Le probleme de la terminaison des programmesest fondamental en programmation. Il faut toujours se demander si le programme quonecrit va terminer. Dun point de vue theorique, il est impossible de trouver un algo-rithme pour faire cela (cf. chapitre 6). Dun point de vue pratique, on doit examinerchaque boucle ou iteration et prouver que chacune termine.

    Voici quelques erreurs classiques, qui toutes simulent le mouvement perpetuel :

    int i = 0 ;

    while(true)

    i++;

    ou bien

    for(i = 0; i >= 0; i++)

    ;

    On sattachera a prouver que les algorithmes que nous etudions terminent bien.

    2.5 Instructions de rupture de controle

    Il y a trois telles instructions qui sont return, break et continue. Linstructionreturn doit etre utilisee dans toutes les fonctions qui calculent un resultat (cf. chapitresuivant).

    Les deux autres instructions de rupture sont beaucoup moins utilisees et peuventetre omises en premiere lecture. Linstruction break permet dinterrompre une suitedinstructions dans une boucle pour passer a linstruction qui suit la boucle dans letexte du programme.

    Linstruction continue a un effet similaire a celui de break, mais redonne le

    controle a literation suivante de la boucle au lieu den sortir.

    2.6 Exemples

    2.6.1 Methode de Newton

    On rappelle que si f est une fonction suffisamment raisonnable de la variable reellex, alors la suite

    xn+1 = xn f(xn)f(xn)

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    31/252

    2.6. EXEMPLES 29

    converge vers une racine de f a partir dun point de depart bien choisi.

    Si f(x) = x2

    a avec a > 0, la suite converge vers a. Dans ce cas particulier, larecurrence secrit :

    xn+1 = xn (x2n a)/(2xn) =1

    2

    xn +

    a

    xn

    .

    La suite (xn) converge, car elle est decroissante, minoree par

    a. On en deduit quela suite |xn+1 xn| tend vers 0. On itere la suite en partant de x0 = a, et on sarretequand la difference entre deux valeurs consecutives est plus petite que > 0 donne.Cette facon de faire est plus stable numeriquement (et moins couteuse) que de tester|x2n a| . Si on veut calculer

    2 par cette methode en Java, on ecrit :

    public class Newton{

    public static void main(String[] args){double a = 2.0, x, xold, eps;

    x = a ;

    eps = 1e-10;

    do{

    // recopie de la valeur ancienne

    xold = x;

    // calcul de la nouvelle valeur

    x = (xold+a/xold)/2;

    System.out.println(x);

    } while(Math.abs(x-xold) > eps);

    System.out.print("Sqrt(a)=");

    System.out.println(x);

    return;

    }

    }

    ce qui donne :

    1.5

    1.4166666666666665

    1.4142156862745097

    1.4142135623746899

    1.4142135623730949

    Sqrt(a)=1.4142135623730949

    On peut egalement verifier le calcul en comparant avec la fonction Math.sqrt() deJava.

    Comment prouve-t-on que cet algorithme termine ? On aborde ici un point parfoisepineux. En effet, nous avons montre que la suite (xn) tend mathematiquement versune limite, et que donc, mathematiquement, la difference |xn xn1| tend vers 0. Lesflottants utilises par les langages de programmation sont une pauvre approximationdes reels. Il convient donc detre prudent dans leur utilisation, ce qui est un sujet derecherche et dapplications tres riche et important.

    Pour illustrer les problemes de convergence, essayez de faire varier la valeur de laconstante eps du programme.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    32/252

    30 CHAPITRE 2. SUITE DINSTRUCTIONS

    Exercice 1. On considere la suite calculant 1/

    a par la methode de Newton, en

    utilisant f(x) = a 1/x2

    :

    xn+1 =xn2

    (3 ax2n).

    Ecrire une fonction Java qui calcule cette suite, et en deduire le calcul de

    a. Cettesuite converge-t-elle plus ou moins vite que la suite donnee ci-dessus ?

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    33/252

    Chapitre 3

    Methodes : theorie et pratique

    Nous donnons dans ce chapitre un apercu general sur lutilisation des methodes(fonctions) dans un langage de programmation classique, sans nous occuper de laproblematique ob jet, sur laquelle nous reviendrons dans le chapitre 5.

    3.1 Pourquoi ecrire des methodes

    Reprenons lexemple du chapitre precedent :

    public class Newton{

    public static void main(String[] args){

    double a = 2.0, x, xold, eps;

    x = a ;

    eps = 1e-10;

    do{

    // recopie de la valeur ancienne

    xold = x;

    // calcul de la nouvelle valeur

    x = (xold+a/xold)/2;

    System.out.println(x);

    } while(Math.abs(x-xold) > eps);

    System.out.print("Sqrt(a)=");

    System.out.println(x);

    return;

    }

    }

    Nous avons ecrit le programme implantant lalgorithme de Newton dans la methodedappel (la methode main). Si nous avons besoin de faire tourner lalgorithme pourplusieurs valeurs de a dans le meme temps, nous allons devoir recopier le programmea chaque fois. Le plus simple est donc decrire une methode a part, qui ne fait que lescalculs lies a Newton :

    public class Newton2{

    31

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    34/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    35/252

    3.2. COMMENT ECRIRE DES METHODES 33

    Le resultat du calcul de la methode doit etre indique apres un return. Il est

    obligatoire de prevoir une telle instruction dans toutes les branches dune methode.Lexecution dun return a pour effet dinterrompre le calcul de la methode en rendantle resultat a lappelant.

    On fait appel a une methode par

    nomFonction(var1, var2, ... , vark)

    En general cet appel se situe dans une affectation.En resume, une syntaxe tres courante est la suivante :

    public static typeRes nomFonction(type1 nom1, ..., typek nomk){

    typeRes r;

    r = ...;

    return r;}

    ...

    public static void main(String[] args){

    type1 n1;

    type2 n2;

    ...

    typek nk;

    typeRes s;

    ...

    s = nomFonction(n1, n2, ..., nk);

    ...

    return;

    }

    3.2.2 Le type special void

    Le type du resultat peut etre void, dans ce cas la methode ne rend pas de resultat.Elle opere par effet de bord, par exemple en affichant des valeurs a lecran ou en modi-fiant des variables globales. Il est deconseille decrire des methodes qui procedent pareffet de bord, sauf bien entendu pour les affichages.

    Un exemple typique est celui de la procedure principale :

    // Voici mon premier programme

    public class Premier{

    public static void main(String[] args){

    System.out.println("Bonjour !");

    return;

    }

    }

    Notons que le return nest pas obligatoire dans une methode de type void, amoins quelle ne permette de sortir de la methode dans un branchement. Nous la met-trons souvent pour marquer lendroit ou on sort de la methode, et par souci dho-mogeneite de lecriture.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    36/252

    34 CHAPITRE 3. METHODES : THEORIE ET PRATIQUE

    3.2.3 La surcharge

    En Java on peut definir plusieurs methodes qui ont le meme nom a condition queleurs signatures soient differentes. On appelle surcharge cette possibilite. Le compilateurdoit etre a meme de determiner la methode dont il est question a partir du type desparametres dappel. En Java, loperateur + est surcharge : non seulement il permetde faire des additions, mais il permet de concatener des chanes de caracteres (voir lasection 5.5 pour plus dinformation). Par exemple, reprenant le programme de calculde racine carree, on aurait pu ecrire :

    public static void main(String[] args){

    double r;

    r = sqrtNewton(2, 1e-10);

    System.out.println("Sqrt(2)=" + r);}

    3.3 Visibilite des variables

    Les arguments dune methode sont passes par valeurs, cest a dire que leur valeurssont recopiees lors de lappel. Apres la fin du travail de la methode les nouvelles valeurs,qui peuvent avoir ete attribuees a ces variables, ne sont plus accessibles.

    Ainsi il nest pas possible decrire une methode qui echange les valeurs de deuxvariables passees en parametre, sauf a proceder par des moyens detournes peu recom-mandes.

    Reprenons lexemple donne au premier chapitre :// Calcul de circonference

    public class Cercle{

    static float p i = (float)Math.PI;

    public static float circonference(float r) {

    return 2. * pi * r;

    }

    public static void main(String[] args){

    float c = circonference (1.5);

    System.out.print("Circonference: ");System.out.println(c);

    return;

    }

    }

    La variable r presente dans la definition de circonference est instanciee aumoment de lappel de la methode par la methode main. Tout se passe comme si leprogramme realisait laffectation r = 1.5 au moment dentrer dans f.

    Dans lexemple precedent, la variable pi est une variable de classe, ce qui veut direquelle est connue et partagee par toutes les methodes presentes dans la classe (ainsi

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    37/252

    3.3. VISIBILITE DES VARIABLES 35

    que par tous les objets de la classe, voir chapitre 5), ce qui explique quon peut lutiliser

    dans la methode circonference.Pour des raisons de proprete des programmes, on ne souhaite pas quil existe beau-coup de ces variables de classe. Lideal est que chaque methode travaille sur ses propresvariables, independamment des autres methodes de la classe, autant que cela soit pos-sible. Regardons ce qui se passe quand on ecrit :

    public class Essai{

    public static int f(int n){

    int m = n+1;

    return 2*m;

    }

    public static void main(String[] args){System.out.print("resultat=");

    System.out.println(f(4));

    return;

    }

    }

    La variable m nest connue (on dit vue) que par la methode f. En particulier, on nepeut lutiliser dans la methode main ou toute autre methode qui serait dans la classe.

    Compliquons encore :

    public class Essai{

    public static int f(int n){

    int m = n+1;

    return 2*m;

    }

    public static void main(String[] args){

    int m = 3 ;

    System.out.print("resultat=");

    System.out.print(f(4));

    System.out.print(" m=");

    System.out.println(m);

    return;

    }

    }

    Quest-ce qui saffiche a lecran ? On a le choix entre :

    resultat=10 m=5

    ou

    resultat=10 m=3

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    38/252

    36 CHAPITRE 3. METHODES : THEORIE ET PRATIQUE

    Dapres ce quon vient de dire, la variable m de la methode f nest connue que de f,

    donc pas de main et cest la seconde reponse qui est correcte. On peut imaginer quela variable m de f a comme nom reel m-de-la-methode-f, alors que lautre a pournom m-de-la-methode-main. Le compilateur et le programme ne peuvent donc pasfaire de confusion.

    3.4 Quelques conseils pour ecrire un (petit) programme

    Un beau programme est difficile a decrire, a peu pres aussi difficile a caracteriserquun beau tableau, ou une belle preuve. Il existe quand meme quelques regles simples.Le premier lecteur dun programme est soi-meme. Si je narrive pas a me relire, il estdifficile de croire que quelquun dautre le pourra. On peut etre amene a ecrire unprogramme, le laisser dormir pendant quelques mois, puis avoir a le reutiliser. Si le

    programme est bien ecrit, il sera facile a relire.Grosso modo, la demarche decriture de petits ou gros programmes est a peu pres la

    meme, a un facteur dechelle pres. On decoupe en tranches independantes le problemea resoudre, ce qui conduit a isoler des methodes a ecrire. Une fois cette architecturemise en place, il ny a plus qua programmer chacune de celles-ci. Meme apres undecoupage a priori du programme en methodes, il arrive quon soit amene a ecriredautres methodes. Quand le decide-t-on ? De facon generale, pour ne pas dupliquer ducode. Une autre regle simple est quun morceau de code ne doit jamais depasser unepage decran. Si cela arrive, on doit couper en deux ou plus. La clarte y gagnera.

    La methode main dun programme Java doit ressembler a une sorte de table desmatieres de ce qui va suivre. Elle doit se contenter dappeler les principales methodesdu programme. A priori, elle ne doit pas faire de calculs elle-meme.

    Les noms de methode (comme ceux des variables) ne doivent pas se resumer a unelettre. Il est tentant pour un programmeur de succomber a la facilite et dimaginerpouvoir programmer toutes les methodes du monde en reutilisant sans cesse les memesnoms de variables, de preference avec un seul caractere par variable. Faire cela conduitrapidement a ecrire du code non lisible, a commencer par soi. Ce style de programmationest donc proscrit. Les noms doivent etre pertinents. Nous aurions pu ecrire le programmeconcernant les cercles de la facon suivante :

    public class D{

    static float z = (float)Math.PI;

    public static float e(float s){

    return 2. * z * s;

    }

    public static void main(String[] args){

    float y = e(1.5);

    System.out.println(y);

    return;

    }

    }

    ce qui aurait rendu la chose un peu plus difficile a lire.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    39/252

    3.4. QUELQUES CONSEILS POUR ECRIRE UN (PETIT) PROGRAMME 37

    Un programme doit etre aere : on ecrit une instruction par ligne, on ne megotte

    pas sur les lignes blanches. De la meme facon, on doit commenter ses programmes.Il ne sert a rien de mettre des commentaires triviaux a toutes les lignes, mais tousles points difficiles du programme doivent avoir en regard quelques commentaires. Unbon debut consiste a placer au-dessus de chaque methode que lon ecrit quelques lignesdecrivant le travail de la methode, les parametres dappel, etc. Que dire de plus sur lesujet ? Le plus important pour un programmeur est dadopter rapidement un style deprogrammation (nombre despaces, placement des accolades, etc.) et de sy tenir.

    Finissons avec un programme horrible, qui est le contre-exemple typique a ce quiprecede :

    public class mystere{public static void main(String[] args){int

    z=

    Integer.parseInt(args[0]);doif((z%2)==0)z

    /=2;

    else z=3*z+1;while(z>1);}}

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    40/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    41/252

    Chapitre 4

    Tableaux

    La possibilite de manipuler des tableaux se retrouve dans tous les langages de pro-grammation ; toutefois Java, qui est un langage avec des objets, manipule les tableauxdune facon particuliere que lon va decrire ici.

    4.1 Declaration, construction, initialisation

    Lutilisation dun tableau permet davoir a sa disposition un tres grand nombrede variables en utilisant un seul nom et donc en effectuant une seule declaration. Eneffet, si on declare un tableau de nom tab et de taille n contenant des valeurs de typetyp, on a a sa disposition les variables tab[0],tab[1], ..., tab[n-1] qui secomportent comme des variables ordinaires de type typ.

    En Java, on separe la declaration dune variable de type tableau, la constructioneffective dun tableau et linitialisation du tableau.

    La declaration dune variable de type tableau de nom tab dont les elements sontde type typ, seffectue par1 :

    typ[] tab;

    Lorsque lon a declare un tableau en Java on ne peut pas encore lutiliser comple-tement. Il est en effet interdit par exemple daffecter une valeur aux variables tab[i],car il faut commencer par construire le tableau, ce qui signifie quil faut reserver de laplace en memoire (on parle dallocation memoire) avant de sen servir.

    Loperation de construction seffectue en utilisant un new, ce qui donne :

    tab = new typ[taille];

    Dans cette instruction, taille est une constante entiere ou une variable de type entierdont levaluation doit pouvoir etre effectuee a lexecution. Une fois quun tableau estcree avec une certaine taille, celle-ci ne peut plus etre modifiee.

    On peut aussi regrouper la declaration et la construction en une seule ligne par :

    typ[] tab = new typ[taille];

    1ou de maniere equivalente par typ tab[] ;. Nous prefererons la premiere facon de faire car ellerespecte la convention suivant laquelle dans une declaration, le type dune variable figure completementavant le nom de celle-ci. La seconde correspond a ce qui se fait en langage C.

    39

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    42/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    43/252

    4.2. REPRESENTATION EN MEMOIRE ET CONSEQUENCES 41

    Le programmeur moderne na pas a se soucier des adresses reelles, il laisse ce soin au

    compilateur (et au programme). Aux temps historiques, la programmation se faisait enmanipulant directement les adresses memoire des objets, ce qui etait pour le moins peuconfortable2.

    Quand on ecrit :

    int i = 3, j;

    une case memoire3 est reservee pour chaque variable, et celle pour i remplie avec lavaleur 3. Quand on execute :

    j = i ;

    le programme va chercher la valeur presente dans la case affectee a i et la recopie dansla case correspondant a j.

    Que se passe-t-il maintenant quand on declare un tableau ?

    int[] tab;

    Le compilateur reserve de la place pour la variable tab correspondante, mais pour lemoment, aucune place nest reservee pour les elements qui constitueront tab. Cest cequi explique que quand on ecrit :

    public class Bug1{

    public static void main(String[] args){

    int[] tab;

    tab[0] = 1;

    }}

    on obtient a lexecution :

    java.lang.NullPointerException at Bug1.main(Bug1.java:5)

    Cest une erreur tellement frequente que les compilateurs recents detectent ce genre deprobleme a la compilation (si possible).

    Quand on manipule un tableau, on travaille en fait de facon indirecte avec lui,comme si on utilisait une armoire pour ranger ses affaires. Il faut toujours imaginerquecrire

    tab[2] = 3;

    veut dire au compilateur retrouve lendroit ou tu as stocke tab en memoire et met ajour la case dindice 2 avec 3. En fait, le compilateur se rappelle dabord ou il a rangeson armoire, puis en deduit quel tiroir utiliser.

    La valeur dune variable tableau est une reference, cest-a-dire ladresse ou elle estrangee en memoire. Par exemple, la suite dinstructions suivante va avoir leffet indiquedans la memoire :

    2Temperons un peu : dans des applications critiques (cartes a puce par exemple), on sait encoredescendre a ce niveau la, quand on sait mieux que le compilateur comment gerer la memoire. Ce sujetdepasse le cadre du cours, mais est enseigne en annee 2.

    3Une case memoire pour un int de Java est formee de 4 octets consecutifs.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    44/252

    42 CHAPITRE 4. TABLEAUX

    int[] t; t

    @0 null

    t=new int[3]; t

    @10@10 : t[0] @14 : t[1] @18 : t[2]

    0 0 0

    t[0]=2; t

    @10@10 : t[0] @14 : t[1] @18 : t[2]

    2 0 0

    Apres allocation, le tableau t est repere par son adresse @10, et les trois cases parles adresses @10, @14 et @18. On remplit alors t[0] avec le nombre 2.

    Expliquons maintenant ce qui se passe quand on ecrit, avec lidee de faire une copiede t :

    int[] t = {1, 2, 3}; // t = @500

    int[ ] u = t ; // u = @500

    u[0] = 0;

    System.out.println(t[0]);

    Les variables u et t designent le meme tableau, en programmation on dit quelles

    font reference au meme tableau, cest-a-dire a la meme suite demplacements dans lamemoire

    t

    u t.length t[0] t[1] t[2]

    3 0 2 3

    Cest ce qui explique que modifier u[0], cest modifier lemplacement memoire refe-rence par u, emplacement qui est egalement reference par t. Et donc le programmeaffiche la nouvelle valeur de t[0], a savoir 0.

    Si on souhaite recopier le contenu dun tableau dans un autre il faut ecrire unefonction :

    public static int[] copier(int[] x){int n = x.length;

    int[ ] y = new int[n];

    for(int i = 0; i < n; i++)

    y[i] = x[i];

    return y;

    }

    Noter aussi que loperation de comparaison de deux tableaux x = = y est evalueea true dans le cas ou x et y referencent le meme tableau (par exemple si on a effectue

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    45/252

    4.3. TABLEAUX A PLUSIEURS DIMENSIONS, MATRICES 43

    laffectation y = x). Si on souhaite verifier legalite des contenus, il faut ecrire une

    fonction particuliere : public static boolean estEgal(int[] x, int[] y){

    if(x.length != y.length) return false;

    for(int i = 0; i < x.length; i++)

    if(x[i] != y[i])

    return false;

    return true;

    }

    Dans cette fonction, on compare les elements terme a terme et on sarrete des quedeux elements sont distincts, en sortant de la boucle et de la fonction dans le mememouvement.

    4.3 Tableaux a plusieurs dimensions, matrices

    Un tableau a plusieurs dimensions est considere en Java comme un tableau de ta-bleaux. Par exemple, les matrices sont des tableaux a deux dimensions, plus precisementdes tableaux de lignes. Leur declaration peut se faire par :

    typ[][] tab;

    On doit aussi le construire a laide de new. Linstruction

    tab = new typ[N][M];

    construit un tableau a deux dimensions, qui est un tableau de N lignes a M colonnes.Linstruction tab.length retourne le nombre de lignes, alors que tab[i].lengthretourne la longueur du tableau tab[i], cest-a-dire le nombre de colonnes.

    On peut aussi, comme pour les tableaux a une dimension, faire une affectation devaleurs en une seule fois :

    int[2][3] tab = {{1,2,3},{4,5,6}};

    qui declare et initialise un tableau a 2 lignes et 3 colonnes. On peut ecrire de faconequivalente :

    int[][] tab = {{1,2,3},{4,5,6}};

    Comme une matrice est un tableau de lignes, on peut fabriquer des matrices bizarres.Par exemple, pour declarer une matrice dont la premiere ligne a 5 colonnes, la deuxiemeligne 1 colonne et la troisieme 2, on ecrit

    public static void main(String[] args){

    int[][] M = new int[3][];

    M[0] = new int[5];

    M[1] = new int[1];

    M[2] = new int[2];

    }

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    46/252

    44 CHAPITRE 4. TABLEAUX

    Par contre, linstruction :

    int[][] N = new int[][3];

    est incorrecte. On ne peut definir un tableau de colonnes.On peut continuer a ecrire un petit programme qui se sert de cela :

    class Tab3{

    static void ecrire(int[] t){

    for(int j = 0; j < t.length; j++)

    System.out.println(t[j]);

    }

    public static void main(String[] args){

    int[][] M = new int[3][];

    M[0] = new int[5];

    M[1] = new int[1];

    M[2] = new int[2];

    for(int i = 0; i < M.length; i++)

    ecrire(M[i]);

    }

    }

    4.4 Les tableaux comme arguments de fonction

    Les valeurs des variables tableaux (les references) peuvent etre passees en argument,on peut aussi les retourner :

    class Tab2{

    static int[] construire(int n){

    int[ ] t = new int[n];

    for(int i = 0; i < n; i++)

    t[i] = i;

    return t;

    }

    public static void main(String[] args){

    int[] t = construire(3);

    for(int i = 0; i < t.length; i++)

    System.out.println(t[i]);

    }

    }

    Considerons maintenant le programme suivant :

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    47/252

    4.5. EXEMPLES DUTILISATION DES TABLEAUX 45

    public class Test{

    public static void f(int[] t){

    t[0] = -10;

    return;

    }

    public static void main(String[] args){

    int[] t = {1, 2, 3};

    f(t);

    System.out.println("t[0]="+t[0]);

    return;

    }}

    Que saffiche-t-il ? Pas 1 comme on pourrait le croire, mais 10. En effet, nousvoyons la un exemple de passage par reference : le tableau t nest pas recopie a lentreede la fonction f, mais on a donne a la fonction f la reference de t, cest-a-dire le moyende savoir ou t est garde en memoire par le programme. On travaille donc sur le tableaut lui-meme. Cela permet deviter des recopies fastidieuses de tableaux, qui sont souventtres gros. La lisibilite des programmes peut sen ressentir, mais cest la facon courantede programmer.

    4.5 Exemples dutilisation des tableaux4.5.1 Algorithmique des tableaux

    Nous allons ecrire des fonctions de traitement de problemes simples sur des tableauxcontenant des entiers.

    Commencons par remplir un tableau avec des entiers aleatoires de [0, M[, on ecrit :

    public class Tableaux{

    static int M = 128;

    // initialisation

    public static int[] aleatoire(int N){int[ ] t = new int[N];

    for(int i = 0; i < N; i++)

    t[i] = (int)(M * Math.random());

    return t;

    }

    }

    Ici, il faut convertir de force le resultat de Math.random()*M en entier de maniereexplicite, car Math.random() retourne un double.

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    48/252

    46 CHAPITRE 4. TABLEAUX

    Pour tester facilement les programmes, on ecrit aussi une fonction qui affiche les

    elements dun tableau t, un entier par ligne :

    // affichage a lecran

    public static void afficher(int[] t){

    for(int i = 0; i < t.length; i++)

    System.out.println(t[i]);

    return;

    }

    Le tableau t etant donne, un nombre m est-il element de t ? On ecrit pour celaune fonction qui retourne le plus petit indice i pour lequel t[i]=m sil existe et 1 siaucun indice ne verifie cette condition :

    // retourne le plus petit i tel que t[i] = m sil existe

    // et -1 sinon.

    public static int recherche(int[] t, int m){

    for(int i = 0; i < t.length; i++)

    if(t[i] == m)

    return i;

    return -1;

    }

    Passons maintenant a un exercice plus complexe. Le tableau t contient des entiersde lintervalle [0, M 1] qui ne sont eventuellement pas tous distincts. On veut savoirquels entiers sont presents dans le tableau et a combien dexemplaire. Pour cela, on

    introduit un tableau auxiliaire compteur, de taille M, puis on parcourt t et pourchaque valeur t[i] on incremente la valeur compteur[t[i]].

    A la fin du parcourt de t, il ne reste plus qua afficher les valeurs non nulles contenuesdans compteur :

    public static void afficher(int[] compteur){

    for(int i = 0; i < M; i++)

    if(compteur[i] > 0){

    System.out.print(i+" est utilise ");

    System.out.println(compteur[i]+" fois");

    }

    }

    public static void compter(int[] t){

    int[] compteur = new int[M];

    for(int i = 0; i < M; i++)

    compteur[i] = 0;

    for(int i = 0; i < t.length; i++)

    compteur[t[i]] += 1;

    afficher(compteur);

    }

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    49/252

    4.5. EXEMPLES DUTILISATION DES TABLEAUX 47

    4.5.2 Un peu dalgebre lineaire

    Un tableau est la structure de donnee la plus simple qui puisse representer unvecteur. Un tableau de tableaux represente une matrice de maniere similaire. Ecrivonsun programme qui calcule loperation de multiplication dun vecteur par une matrice agauche. Si v est un vecteur colonne a m lignes et A une matrice n m, alors w = Avest un vecteur colonne a n lignes. On a :

    wi =m1k=0

    Ai,kvk

    pour 0 i < n. On ecrit dabord la multiplication :

    static double[] multMatriceVecteur(double[][] A,double[] v){

    int n = A.length;

    int m = A[0].length;

    double[ ] w = new double[n];

    // calcul de w = A * v

    for(int i = 0; i < n; i++){

    w[i] = 0;

    for(int k = 0 ; k < m ; k + + )

    w[i] += A[i][k] * v[k];

    }return w;

    }

    static double[] multMatriceVecteur(double[][] A,

    double[] v){

    int n = A.length;

    int m = A[0].length;

    double[ ] w = new double[n];

    // calcul de w = A * v

    for(int i = 0; i < n; i++){w[i] = 0;

    for(int k = 0 ; k < m ; k + + )

    w[i] += A[i][k] * v[k];

    }

    return w;

    }

    puis le programme principal :

    public static void main(String[] args){

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    50/252

    48 CHAPITRE 4. TABLEAUX

    int n = 3 , m = 4 ;

    double[][] A = new double[n][m]; / / A e s t n x mdouble[ ] v = new double[m]; / / v e s t m x 1

    double[] w;

    // initialisation de A

    for(int i = 0; i < n; i++)

    for(int j = 0 ; j < m ; j + + )

    A[i][j] = Math.random();

    // initialisation de v

    for(int i = 0; i < m; i++)

    v[i] = Math.random();

    w = multMatriceVecteur(A, v); // (*)

    // affichage

    for(int i = 0; i < n; i++)

    System.out.println("w["+i+"]="+w[i]);

    return;

    }

    public static void main(String[] args){

    int n = 3 , m = 4 ;double[][] A = new double[n][m]; / / A e s t n x m

    double[ ] v = new double[m]; / / v e s t m x 1

    double[] w;

    // initialisation de A

    for(int i = 0; i < n; i++)

    for(int j = 0 ; j < m ; j + + )

    A[i][j] = Math.random();

    // initialisation de v

    for(int i = 0; i < m; i++)

    v[i] = Math.random();

    w = multMatriceVecteur(A, v); // (*)

    // affichage

    for(int i = 0; i < n; i++)

    System.out.println("w["+i+"]="+w[i]);

    return;

    }

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    51/252

    4.5. EXEMPLES DUTILISATION DES TABLEAUX 49

    On peut recrire la fonction de multiplication en passant les arguments par effets de

    bord sans avoir a creer le resultat dans la fonction, ce qui peut etre couteux quand ondoit effectuer de nombreux calculs avec des vecteurs. On ecrit alors plutot :

    static void multMatriceVecteur(double[] w,

    double[][] A,

    double[] v){

    int n = A.length;

    int m = A[0].length;

    // calcul de w = A * v

    for(int i = 0; i < n; i++){

    w[i] = 0;

    for(int k = 0 ; k < m ; k + + )

    w[i] += A[i][k] * v[k];

    }

    }

    static void multMatriceVecteur(double[] w,

    double[][] A,

    double[] v){

    int n = A.length;

    int m = A[0].length;

    // calcul de w = A * v

    for(int i = 0; i < n; i++){

    w[i] = 0;

    for(int k = 0 ; k < m ; k + + )

    w[i] += A[i][k] * v[k];

    }

    }

    Dans le programme principal, on remplacerait la ligne (*) par :

    w = new double[n];

    multMatriceVecteur(w, A, v);

    4.5.3 Le crible dEratosthene

    On cherche ici a trouver tous les nombres premiers de lintervalle [1, N]. La solutiondeja connue des Grecs consiste a ecrire tous les nombres de lintervalle les uns a la suitedes autres. Le plus petit nombre premier est 2. On raye alors tous les multiples de 2plus grands que 2 de lintervalle, ils ne risquent pas detre premiers. Le premier nombrequi na pas ete raye au-dela du nombre premier courant est lui-meme premier, cestle suivant a traiter. On raye ainsi les multiples de 3 sauf 3, etc. On sarrete quand on

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    52/252

    50 CHAPITRE 4. TABLEAUX

    sapprete a eliminer les multiples de p >

    N (rappelons que tout nombre non premier

    plus petit que N a un diviseur premier N).Comment modeliser le crible ? On utilise un tableau de booleens estpremier,

    de taille N + 1, qui representera lintervalle [1, N]. Il est initialise a true au depart,

    car aucun nombre nest raye. A la fin du calcul, p 2 est premier si et seulement siestpremier[p] == true. On trouve le programme complet dans la figure 4.1.

    Remarquons que la ligne

    k p = 2*p;

    peut etre avantageusement remplacee par

    k p = p*p;

    car tous les multiples de p de la forme up avec u < p ont deja ete rayes du tableau aune etape precedente.Il existe de nombreuses astuces permettant daccelerer le crible. Notons egalement

    que lon peut se servir du tableau des nombres premiers pour trouver les petits facteursde petits entiers. Ce nest pas la meilleure methode connue pour trouver des nombrespremiers ou factoriser les nombres qui ne le sont pas. Revenez donc me voir en coursde Cryptologie si ca vous interesse.

    4.5.4 Jouons a la bataille rangee

    On peut egalement se servir de tableaux pour representer des objets a priori pluscompliques. Nous allons decrire ici une variante simplifiee du celebre jeu de bataille,que nous appelerons bataille rangee. La regle est simple : le donneur distribue 32 cartes(numerotees de 1 a 32) a deux joueurs, sous la forme de deux piles de cartes, face surle dessous. A chaque tour, les deux joueurs, appeles Alice et Bob, retournent la cartedu dessus de leur pile. Si la carte dAlice est plus forte que celle de Bob, elle marqueun point ; si sa carte est plus faible, cest Bob qui marque un point. Gagne celui desdeux joueurs qui a marque le plus de points a la fin des piles.

    Le programme de jeu doit contenir deux phases : dans la premiere, le programme batet distribue les cartes entre les deux joueurs. Dans un second temps, le jeu se deroule.

    Nous allons stocker les cartes dans un tableau donne[0..32[ avec la conventionque la carte du dessus se trouve en position 31.

    Pour la premiere phase, battre le jeu revient a fabriquer une permutation au ha-sard des elements du tableau donne. Lalgorithme le plus efficace pour cela utilise ungenerateur aleatoire (la fonction Math.random() de Java, qui renvoie un reel aleatoire

    entre 0 et 1), et fonctionne selon le principe suivant. On commence par tirer un indicej au hasard entre 0 et 31 et on permute donne[j] et donne[31]. On continue alorsavec le reste du tableau, en tirant un indice entre 0 et 30, etc. La fonction Java estalors (nous allons ici systematiquement utiliser le passage par reference des tableaux) :

    static void battre(int[] donne){

    int n = donne.length, i, j, tmp;

    for(i = n-1; i > 0; i--){

    // on choisit un entier j de [0..i]

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    53/252

    4.5. EXEMPLES DUTILISATION DES TABLEAUX 51

    // Retourne le tableau des nombres premiers

    // de lintervalle [2..N]

    public static int[] Eratosthene(int N){

    boolean[] estpremier = new boolean[N+1];

    int p, kp, nbp;

    // initialisation

    for(int n = 2; n < N+1; n++)

    estpremier[n] = true;

    // boucle d{\e}liminationp = 2 ;

    while(p*p

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    54/252

    52 CHAPITRE 4. TABLEAUX

    j = (int)(Math.random() * (i+1));

    // on permute donne[i] et donne[j]tmp = donne[i];

    donne[i] = donne[j];

    donne[j] = tmp;

    }

    }

    static void battre(int[] donne){

    int n = donne.length, i, j, tmp;

    for(i = n-1; i > 0; i--){

    // on choisit un entier j de [0..i]

    j = (int)(Math.random() * (i+1));

    // on permute donne[i] et donne[j]

    tmp = donne[i];

    donne[i] = donne[j];

    donne[j] = tmp;

    }

    }

    La fonction qui cree une donne a partir dun paquet de n cartes est alors :

    static int[] creerJeu(int n){

    int[] jeu = new int[n];

    for(int i = 0; i < n; i++)

    jeu[i] = i+1;

    battre(jeu);

    return jeu;

    }

    static int[] creerJeu(int n){

    int[] jeu = new int[n];

    for(int i = 0; i < n; i++)

    jeu[i] = i+1;

    battre(jeu);

    return jeu;

    }

    et nous donnons maintenant le programme principal :

    public static void main(String[] args){

    int[] donne;

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    55/252

    4.5. EXEMPLES DUTILISATION DES TABLEAUX 53

    donne = creerJeu(32);afficher(donne);

    jouer(donne);

    }

    public static void main(String[] args){

    int[] donne;

    donne = creerJeu(32);

    afficher(donne);

    jouer(donne);

    }

    Nous allons maintenant jouer. Cela se passe en deux temps : dans le premier, le donneurdistribue les cartes entre les deux joueurs, Alice et Bob. Dans le second, les deux joueurs

    jouent, et on affiche le nom du vainqueur, celui-ci etant determine a partir du signe dugain dAlice (voir plus bas) :

    static void jouer(int[] donne){

    int[] jeuA = new int[donne.length/2];

    int[] jeuB = new int[donne.length/2];

    int gainA;

    distribuer(jeuA, jeuB, donne);

    gainA = jouerAB(jeuA, jeuB);

    if(gainA > 0) System.out.println("A gagne");

    else if(gainA < 0) System.out.println("B gagne");

    else System.out.println("A et B sont ex aequo");

    }

    static void jouer(int[] donne){

    int[] jeuA = new int[donne.length/2];

    int[] jeuB = new int[donne.length/2];

    int gainA;

    distribuer(jeuA, jeuB, donne);

    gainA = jouerAB(jeuA, jeuB);

    if(gainA > 0) System.out.println("A gagne");

    else if(gainA < 0) System.out.println("B gagne");

    else System.out.println("A et B sont ex aequo");

    }

    Le tableau donne[0..31] est distribue en deux tas, en commencant par Alice, qui varecevoir les cartes de rang pair, et Bob celles de rang impair. Les cartes sont donneesa partir de lindice 31 :

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    56/252

    54 CHAPITRE 4. TABLEAUX

    // donne[] contient les cartes quon distribue a partir

    // de la fin. On remplit jeuA et jeuB a partir de 0

    static void distribuer(int[] jeuA,int[] jeuB,int[] donne){

    int iA = 0, iB = 0;

    for(int i = donne.length-1; i >= 0; i--)

    if((i % 2) == 0)

    jeuA[iA++] = donne[i];

    else

    jeuB[iB++] = donne[i];

    }

    // donne[] contient les cartes quon distribue a partir

    // de la fin. On remplit jeuA et jeuB a partir de 0

    static void distribuer(int[] jeuA,int[] jeuB,int[] donne){

    int iA = 0, iB = 0;

    for(int i = donne.length-1; i >= 0; i--)

    if((i % 2) == 0)

    jeuA[iA++] = donne[i];

    else

    jeuB[iB++] = donne[i];

    }

    On sinteresse au gain dAlice, obtenu par la difference entre le nombre de cartes gagneespar Alice et celles gagnees par Bob. Il suffit de mettre a jour cette variable au cours ducalcul :

    static int jouerAB(int[] jeuA, int[] jeuB){

    int gainA = 0;

    for(int i = jeuA.length-1; i >= 0; i--)

    if(jeuA[i] > jeuB[i])

    gainA++;

    else if(jeuA[i] < jeuB[i])gainA--;

    return gainA;

    }

    static int jouerAB(int[] jeuA, int[] jeuB){

    int gainA = 0;

    for(int i = jeuA.length-1; i >= 0; i--)

    if(jeuA[i] > jeuB[i])

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    57/252

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    58/252

    56 CHAPITRE 4. TABLEAUX

    f 7

    main m = f(3) main m = 7

    Fig. 4.3 Pile des appels (suite).

  • 8/2/2019 Introduction l'Informatique - cours Polytechnique (2011)

    59/252

    Chapitre 5

    Classes, objets

    Ce chapitre est consacre a lorganisation generale dune classe en Java, car jusquicinous nous sommes plutot interesse