Vous êtes sur la page 1sur 53

COURS D’INFORMATIQUE DE MPSI

Guillaume VASSAL

Lycée du Parc des Loges à Évry, le 19 septembre 2018


2
Table des matières

1 Introduction à l’informatique 1
1.1 Architecture d’un ordinateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Représentation des nombres en machine . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Introduction à l’algorithmique 9
2.1 Vocabulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Variables et affectations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4 Fonctions, méthodes et modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.5 Structures de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.6 Compléments d’algorithmique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3 Quelques modules de Python et applications 33


3.1 Le module matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2 Les modules numpy et scipy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3 Ingénierie numérique et simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.4 Lire et écrire dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

4 Initiation aux bases de données 35


4.1 L’algèbre relationnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.2 Opérateurs sur le modèle relationnel . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3 Requêtes SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

Références 47

i
ii TABLE DES MATIÈRES
Chapitre 1

Introduction à l’informatique

Sommaire
1.1 Architecture d’un ordinateur . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Présentation générale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Quelques mots sur les systèmes d’exploitation . . . . . . . . . . . . . . . . . . . 3
1.2 Représentation des nombres en machine . . . . . . . . . . . . . . . . . . . 4
1.2.1 Les nombres entiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2.2 Les nombres réels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.3 Problème de dépassement de capacité . . . . . . . . . . . . . . . . . . . . . . . 7

L’informatique est le domaine d’activité scientifique, technique et industriel concernant le traite-


ment automatique de l’information par des machines : des systèmes embarqués, des ordinateurs, des
robots, des automates, etc . . . Elle est apparue au milieu du 20-ème siècle et a connu une expansion
rapide.

1.1 Architecture d’un ordinateur


1.1.1 Présentation générale
On présente l’architecture de base d’un système à microprocesseur qui permet le traitement pro-
grammé de l’information. On retrouve ces systèmes dans les ordinateurs, tablettes, consoles de jeux,
calculatrices, automobile, la robotique etc . . .
Il faut distinguer la partie matériel et la partie logiciel. Le matériel (Hardware) correspond à l’aspect
concret : unité centrale, mémoire, organes d’entrée-sortie etc . . . La partie logiciel est constituée d’un
ensemble d’instructions, appelé programme, contenu dans l’espace mémoire, définissant les actions
effectuées par le matériel.
L’architecture d’un système à microprocesseur représente l’organisation de ses différentes unités et
de leurs interconnexions. Le concept de microprocesseur a été créé par la Société Intel. Cette Société,
créée en 1968, était spécialisée dans la conception et la fabrication de puces mémoire.

Définition 1.1.1
Le processeur, ou CPU a , est le composant de l’ordinateur qui exécute les programmes informa-
tiques. Un processeur construit en un seul circuit intégré est un microprocesseur.
a. Central Processing Unit, « Unité centrale de traitement ».

Un système à microprocesseur n’effectue que des opérations simples sur des séquences de signaux
électriques. Ces derniers ne peuvent prendre que deux états (potentiel électrique maximum ou mini-
mum) qui sont assimilés aux valeurs 1 et 0. C’est pourquoi un ordinateur de peut comprendre qu’une
suite de 0 et de 1, c’est-à-dire des nombres binaires. Ainsi, toutes les données qu’on utilise (nombres,
textes, images etc . . . ), mais aussi les instructions fournies à la machine sont codées en format binaire.

1
2 CHAPITRE 1. INTRODUCTION À L’INFORMATIQUE

Définition 1.1.2
Un chiffre binaire est l’unité de mesure en informatique désignant la quantité élémentaire d’in-
formations qu’on peut représenter, on l’appelle aussi un bit a .
a. Le mot bit est la contraction des mots anglais binary digit qui signifient « chiffre binaire ».

Définition 1.1.3
Un mot binaire est une suite de 0 et de 1.

Définition 1.1.4
Un octet est un regroupement de 8 bits codant une information.

Dans ce système de codage, un octet permet de représenter 28 , c’est-à-dire 256 valeurs différentes.
Un ou plusieurs octets permettent ainsi de coder des valeurs numériques ou des caractères.
Pour traiter une information, un microprocesseur seul ne suffit pas, il faut l’insérer au sein d’un
système minimum de traitement programmé de l’information. John Von Neumann est à l’origine d’un
modèle de machine universelle (1946) qui sert de base à la plupart des systèmes à microprocesseur
actuels. Elle est composée des éléments suivants :
— une unité centrale,
— une mémoire principale,
— des interfaces d’entrées et de sorties.

Figure 1.1 – Source : Architecture des ordinateurs, T. Dumartin

L’unité centrale est composée d’un le microprocesseur qui est chargé d’interpréter et d’exécuter
les instructions d’un programme, de lire ou de sauvegarder les résultats dans la mémoire et de com-
muniquer avec les unités d’échange. Toutes les activités du microprocesseur sont cadencées par une
horloge. On caractérise le microprocesseur par :
— sa fréquence d’horloge : en MHz 1 ou GHz 2 ,
1. Méga Hertz
2. Giga Hertz
1.1. ARCHITECTURE D’UN ORDINATEUR 3

— le nombre d’instructions par secondes qu’il est capable d’exécuter : en MIPS 3 ,


— la taille des données qu’il est capable de traiter : en bits.
Le premier microprocesseur, le 4004, apparu en 1971, était une unité de calcul 4 bits fonctionnant à 108
kHz. Ils devaient donc exécuter plusieurs instructions pour additionner des nombres de 32 ou 64 bits.
Les microprocesseurs actuels (en 2007) peuvent traiter des nombres sur 64 bits ensemble. Le rôle de
l’horloge est de cadencer le rythme du travail du microprocesseur. Plus la vitesse de l’horloge augmente,
plus le microprocesseur effectue d’instructions en une seconde. La puissance d’un microprocesseur ne
dépend pas seulement de la fréquence du microprocesseur mais aussi de sa structure interne. Dans les
années 1970, les microprocesseurs effectuaient moins d’un million d’instructions par seconde, tandis
que les processeurs actuels peuvent effectuer plus de 100 milliard d’instructions par seconde.
La mémoire principale contient les instructions du ou des programmes en cours d’exécution et les
données associées à ce programme. Physiquement, elle se décompose souvent en deux types :
— Une mémoire morte (ROM = Read Only Memory) chargée de stocker le programme. C’est une
mémoire à lecture seule.
— Une mémoire vive (RAM = Random Access Memory) chargée de stocker les données intermé-
diaires ou les résultats de calculs. On peut y lire ou écrire des données qui seront perdues à la
mise hors tension.
Les disques durs, CDROM, etc . . . sont des périphériques de stockage et sont considérés comme des
mémoires secondaires.
Les interfaces d’entrées et de sorties permettent d’assurer la communication entre le microproces-
seur et les périphériques : capteur, clavier, moniteur ou afficheur, imprimante etc . . .
Un bus informatique est un système de communication entre les composants d’un ordinateur. On
retrouve trois types de bus véhiculant des informations en parallèle :
— Un bus de données : bidirectionnel, qui assure le transfert des informations entre le micropro-
cesseur et son environnement, et inversement. Son nombre de lignes est égal à la capacité de
traitement du microprocesseur.
— un bus d’adresses : unidirectionnel, qui permet la sélection des informations à traiter dans un
espace mémoire qui peut avoir 2n emplacements, où n est le nombre de conducteurs du bus
d’adresses.
— Un bus de commande : constitué par quelques conducteurs qui assurent la synchronisation des
flux d’informations sur les bus des données et des adresses.
La multiplication des périphériques autour du microprocesseur oblige la présence d’un décodeur
d’adresse chargé d’aiguiller les données présentes sur le bus de données.

1.1.2 Quelques mots sur les systèmes d’exploitation

Définition 1.1.5
Un système d’exploitation a est un ensemble de programmes qui dirige l’utilisation des capacités
d’un ordinateur par des logiciels d’applications.
a. aussi appelé OS pour Operating System

Le système d’exploitation est le premier programme exécuté lors de la mise en marche de l’ordi-
nateur, après l’amorçage 4 . Il offre une suite de services généraux qui facilitent la création de logiciels
et sert d’intermédiaire entre ces logiciels et le matériel informatique.
Il existe sur le marché des dizaines de systèmes d’exploitation différents. Les deux familles de
systèmes d’exploitation les plus populaires sont la famille Unix (dont Mac OS X, Linux, iOS et Android)
et la famille Windows.

3. Millier d’Instructions Par Seconde


4. Le boot, ou l’amorçage, est la procédure de démarrage d’un ordinateur, qui comporte notamment le chargement
du programme initial.
4 CHAPITRE 1. INTRODUCTION À L’INFORMATIQUE

1.2 Représentation des nombres en machine


1.2.1 Les nombres entiers
Écriture en base 2
On représente de façon usuel les nombres en base 10. Par exemple, on a :

45609 “ 4 ˆ 104 ` 5 ˆ 103 ` 6 ˆ 102 ` 9 ˆ 100 .

Pour tout entier naturel N , on peut écrire :


n
ÿ
N“ ak ˆ 2k , où ak P t0, 1u.
k“0

C’est l’écriture en base 2, ou écriture binaire, de N . Les entiers n, a0 , . . . , an´1 sont uniques. On note
N “ an´1 ¨ ¨ ¨ a0 2 .
Un entier est représenté par un espace mémoire constitué d’octets (8 bits). Le nombre d’octets
pour une unité de stockage dépend de la machine, il peut valoir 1, 2, 3, 4 ou 8 octets à savoir 8, 16,
32 ou 64 bits. Si N “ an´1 ¨ ¨ ¨ a0 2 , les nombres ai sont les bits qui représentent l’entier.

Proposition 1.2.1
Si l’on dispose de n bits, on peut représenter 2n nombres entiers soit un nombre fini.

Il est donc clair qu’on ne peut pas représenter ni calculer tous les nombres dans une machine. A
titre d’exemple, avec 32 bits, on est limité à quelque milliards de nombres, le plus grand étant de cet
ordre de grandeur.

Exemple 1.2.2
Sur 3 bits, on peut représenter 8 entiers le plus grand étant 7 qui est représenté par la suite de
2 2
bits 111. Dans ce système, on ne peut pas additionner 4 “ 100 avec 5 “ 101 sinon on sort des
capacités de stockage.

Dans la suite de ce paragraphe, on décrit deux méthodes pour représenter les entiers relatifs.

Valeur absolue et signe


Pour coder le signe d’un entier, il faut réserver un bit puis les bits restant servent à représenter la
valeur absolue de celui-ci selon la convention standard.
Si pan´1 , . . . , a1 , a0 q est une suite de bits qui représente un entier N , alors an´1 représente le signe
de N (positif si an´1 “ 0 et négatif si an´1 “ 1) et la valeur de N est donnée par :

N “ p1 ´ 2an´1 qpan´2 2n´2 ` ¨ ¨ ¨ ` a1 2 ` a0 q.

Exemple 1.2.3
Dans un système à 8 bits, le nombre ´35 est représenté par la suite de bits 10010011 et le nombre
13 par 00001101.

Par cette méthode 0 possède deux représentations 0 . . . 0 ou 10 . . . 0. De plus, on ne peut plus


additionner bit à bit comme pour les nombres binaires. En effet, on doit d’abord comparer les deux
nombres pour connaître le signe de la somme. Si l’on dispose de n bits, on peut représenter les entiers
´2n´1 ` 1, . . . , ´1, 0, 1, . . . , 2n´1 ´ 1.
1.2. REPRÉSENTATION DES NOMBRES EN MACHINE 5

Remarque 1.2.4
Un entier négatif a est représenté par la représentation standard de l’entier 2n´1 ` |a| “ 2n´1 ´ a.

Remarque 1.2.5
Par cette méthode, on représente 2n ´1 entiers puisque 0 possède deux représentations distinctes.

Complément à 2
La représentation en complément à 2 est la plus courante. Si l’on dispose de n bits on peut
représenter les entiers ´2n´1 , . . . , 0, . . . , 2n´1 ´ 1. Les nombres de 0 à 2n´1 ´ 1 sont représentés par
leur écriture binaire. Les nombres de ´2n´1 , . . . , ´1 sont représentés respectivement par les entiers
2n´1 , . . . , 2n ´ 1.
Soit pan´1 , . . . , a0 q est la suite de bits représentant N par la méthode complément à 2. Le bits an´1
donne le signe de a. En effet, si an´1 “ 1 alors a est strictement négatif, sinon il est positif.

Proposition 1.2.6
L’entier relatif x est représenté par :
1. la représentation standard si x ě 0,
2. la représentation standard de l’entier 2n ´ |x| “ 2n ` x, si x ă 0.

Proposition 1.2.7
Soit m un mot binaire. On note p l’entier naturel correspondant au mot m par la représentation
standard. L’entier correspondant au mot m en complément à 2 est :
1. p, si p ď 2n´1 ´ 1,
2. p ´ 2n , si p ě 2n´1 .

Exemple 1.2.8
On suppose n “ 8. Dans la convention complément 2 :
— le nombre ´1 est représenté par 11111111,
— le nombre 27 ´ 1 est représenté par 01111111,
— le nombre ´27 est représenté par 10000000.
— le nombre ´13 est représenté par 11110011.

Remarque 1.2.9
Dans la pratique, pour coder un entier négatif, il suffit de coder sa valeur absolue, d’échanger les
bits (on remplace les 0 par des 1 et inversement) puis d’ajouter 1.

Exemple 1.2.10
Sur un octet, la représentation de ´4 est 11111100.
6 CHAPITRE 1. INTRODUCTION À L’INFORMATIQUE

Remarque 1.2.11
Dans la pratique, pour représenter l’entier ´p, pour p P N, on peut effectuer la procédure suivante :
1. on donne le mot m représentant p de façon standard.
2. On échange les 0 et les 1 du mot m.
3. on ajoute 1 au mot obtenu.

Remarque 1.2.12
Par cette méthode, on représente bien 2n entiers relatifs dont 2n´1 entiers naturels (donc 2n´1
entiers strictement négatifs).

Remarque 1.2.13
Pour ajouter deux entiers représentés par la méthode complément 2, il suffit de les additionner
bit à bit. Il faut prendre garde au débordement (tous les entiers ne peuvent être représentés). Le
nombre 0 se représente de façon unique.

1.2.2 Les nombres réels


Représentation à virgule flottante
Un nombre décimal a plusieurs écritures possibles. Par exemple, le nombre 3.14159 peut s’écrire
314.159 ˆ 10´2 , 0.314159 ˆ 101 ou encore 0.00034159 ˆ 104 . La partie entière de ce nombre est 3.
Dans l’écriture 314.159 ˆ 10´2 , la partie décimale 314.159 est appelée la mantisse et ´2 est l’exposant.
Lorsqu’on fait varier l’exposant, on fait « flotter la virgule ». Dans l’écriture scientifique des nombres
réels, la mantisse est normalisée : on utilise qu’un seul chiffre non nul avant la virgule décimale.
Plus généralement, en base b, un nombre décimale x se représente de la façon suivante :

x “ m ˆ be , (1.1)

où m est la mantisse telle que 1 ď |m| ă b et e est l’exposant. La mantisse est un nombre décimal
2
exprimé dans la base b. Par exemple, en base 2, on écrit 11.101 “ 21 ` 20 ` 2´1 ` 2´3 “ 3.625.
La représentation en base 10 est utiliser dans les calculatrices tandis que la base 2 est utiliser pour
représenter les réels dans les ordinateurs.

Représentation des réels en base 2


Pour assurer la compatibilité entre machine, une écriture standard a été édicté par l’IEEE 5 : la
norme 754. L’exposant est biaisés : si l’on dispose de N bits, on ajoute 2N ´1 ´ 1 à l’exposant avant de
le représenter en base 2. Ainsi, tout exposant entre ´2N ´1 ` 1 et 2N ´1 est représentable. La mantisse
commence toujours par 1, donc, pour gagner un bit dans la représentation, on omet ce premier chiffre
de la mantisse.
— Représentation 32 bits : 1 bit de signe, exposant sur 8 bit biaisé à 127 “ 28´1 ´ 1 et 23 bits
pour la mantisse (sans le premier chiffre).
— Représentation 64 bits : 1 bit de signe, exposant sur 11 bits biaisé à 1023 “ 211´1 ´ 1 et 52 bits
pour la mantisse.

5. Institute of Electrical and Electronics Engineers


1.2. REPRÉSENTATION DES NOMBRES EN MACHINE 7

Exemple 1.2.14
On considère le nombre réels x codé sur 32 bits par :

1 on 00011110
loomo loooomoooon 01010000000000000000000
loooooooooooooooomoooooooooooooooon .
signe exposant mantisse

1. Premier bits vaut 1 : donc le nombre est négatif.


2
2. Exposant biaisé vaut 00011110 “ 30 donc l’exposant est 30 ´ 127 “ ´97.
2
3. La mantisse est 1.01010000000000000000000 “ 1 ` 2´2 ` 2´4 “ 21{16 “ 1.3625.
Le nombre x est égale à 21{16 ˆ 2´97 “ 21{16 ˆ p210 q´10 23 » 10.5 ˆ 10´30 (car 210 » 103 ), puis
x » 1.05 ˆ 10´29 .

Exemple 1.2.15
2 2
Pour x “ 3, 3125, on a x “ 11.0101 , mais aussi x “ 1, 65625 ˆ 21 “ `1.10101 ˆ 21 .

Exemple 1.2.16
Trouver la représentation sur 32 bits du réel 278. De même pour ´243, 25.

1.2.3 Problème de dépassement de capacité


De nombreuses catastrophes sont attribuables à une mauvaise gestion de l’arithmétique des ordi-
nateurs (erreurs d’arrondis, d’annulation . . . ). Ces erreurs peuvent avoir des conséquence dramatiques.

Missile Patriot
En février 1991, pendant la Guerre du Golfe, une batterie américaine de missiles Patriot, à Dha-
ran (Arabie Saoudite), a échoué dans l’interception d’un missile Scud irakien. Le Scud a frappé un
baraquement de l’armée américaine et a tué 28 soldats. La commission d’enquête a conclu à un calcul
incorrect du temps de parcours, dû à un problème d’arrondi. Les nombres étaient représentés en vir-
gule fixe sur 24 bits, donc 24 chiffres binaires. Le temps était compté par l’horloge interne du système
en 1/10 de seconde. Malheureusement, 1/10 n’a pas d’écriture finie dans le système binaire : 0, 1 (dans
le système décimal) 0, 0001100110011001100110011 . . . (dans le système binaire). L’ordinateur de bord
arrondissait 1{10 à 24 chiffres, d’où une petite erreur dans le décompte du temps pour chaque 1/10
de seconde. Au moment de l’attaque, la batterie de missile Patriot était allumée depuis environ 100
heures, ce qui avait entraîné une accumulation des erreurs d’arrondi de 0,34 s. Pendant ce temps, un
missile Scud parcourt environ 500 m, ce qui explique que le Patriot soit passé à côté de sa cible. Ce
qu’il aurait fallu faire c’était redémarrer régulièrement le système de guidage du missile.

Explosion d’Ariane 5
Le 4 juin 1996, une fusée Ariane 5, a son premier lancement, a explosé 40 secondes après l’allumage.
La fusée et son chargement avaient coûté 500 millions de dollars. La commission d’enquête a rendu son
rapport au bout de deux semaines. Il s’agissait d’une erreur de programmation dans un système. À un
moment donné, un nombre codé en virgule flottante sur 64 bits (qui représentait la vitesse horizontale
de la fusée par rapport à la plate-forme de tir) était converti en un entier sur 16 bits. Malheureusement,
le nombre en question était plus grand que 32768 (overflow), le plus grand entier que l’on peut coder
sur 16 bits, et la conversion a été incorrecte.
8 CHAPITRE 1. INTRODUCTION À L’INFORMATIQUE
Chapitre 2

Introduction à l’algorithmique

Sommaire
2.1 Vocabulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.1 Généralités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.2 Le langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Variables et affectations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2.1 Affectations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2.2 La structure conditionnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.1 L’instruction while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.2 Les boucles for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4 Fonctions, méthodes et modules . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.1 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.2 Les méthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4.3 Les modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.5 Structures de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.5.1 Les chaines de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.5.2 Les listes (suite) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5.3 Les tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.5.4 Les dictionnaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.6 Compléments d’algorithmique . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.6.1 Prouver un algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.6.2 Complexité d’un algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.1 Vocabulaire
2.1.1 Généralités
L’algorithmique est le domaine qui étudie les algorithmes. Le mot algorithme provient du nom du
mathématicien Al-Khawarizmi 1 qui est demeuré célèbre pour avoir introduit dans le monde arabo-
musulman et en Occident la numération décimale (rapportée des Indes).

Définition 2.1.1
Un algorithme est une procédure qui termine en un nombre fini d’étapes et qui a pour but
d’effectuer un calcul ou de résoudre un problème.

1. Al-Khawarizmi, né vers 783, originaire de Khiva dans la région du Khwarezm (Ouzbékistan actuel), est un mathé-
maticien, géographe, astrologue et astronome perse.

9
10 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

Un algorithme est le squelette théorique d’un programme informatique. Il est indépendant de tout
codage particulier qui permettrait sa mise en oeuvre sur un ordinateur. Un algorithme est souvent
écrit dans ce qu’on appelle un pseudo-langage.

Exemple 2.1.2
Pour résoudre une équation du second degré ax2 ` bx ` c “ 0 sur R, on suit l’algorithme suivant :
if a “ 0 then return ERROR
else
∆ “ b2 ´ 4ac
if ∆ ă 0 then return ’Il n’y a pas de solution
? réelle.’ ?
´b ` ∆ ´b ´ ∆
else return ’Les solutions sont x1 “ et x2 “ ’
2a 2a
end if
end if

Définition 2.1.3
Un programme est la traduction d’un algorithme dans un langage de programmation « compré-
hensible » par la machine.

Un langage de programmation est une notation conventionnelle formelle destinée à formuler des
algorithmes et produire des programmes logiciels qui les appliquent. D’une manière similaire à une
langue naturelle, un langage de programmation est fait d’un alphabet, un vocabulaire et de règles de
grammaire dites aussi règles de syntaxe. Les plus populaires sont C, C++, Php, Pascal, Java, Fortran,
COBOL, OCaml, Python . . .
Un langage de programmation est mis en œuvre par un traducteur automatique : compilateur ou
interpréteur. Un compilateur est un programme informatique qui transforme dans un premier temps
un code source écrit dans un langage de programmation donné en un code cible qui pourra être
directement exécuté par un ordinateur (comme en C++ par exemple), tandis que l’interpréteur réalise
cette traduction « à la volée ».
Avant de se lancer dans la transcription d’un algorithme en programme informatique dans un
langage choisi, il faudra répondre à plusieurs questions. Tout d’abord l’algorithme donne-t-il le résultat
attendu ? Il faudra être capable de prouver l’algorithme. Quelles structures de données sont les plus
adaptées pour représenter les objets de l’algorithme ? Et enfin, quelle est la complexité de l’algorithme
(du programme) ? C’est-à-dire, en combien d’opérations, en moyenne, celui-ci termine-t-il ?

2.1.2 Le langage Python


On utilisera le langage Python (version 3) qui permet d’écrire des programmes en utilisant des
symboles mathématiques familiers. Il dispose également d’un grand nombre de fonctions primitives
et de modules, tels que numpy et scipy rendant possible le calcul numérique, ou encore matplotlib
permettant d’afficher des graphiques en deux ou trois dimensions.
Le langage Python est un langage multi-paradigme 2 :
— langage impératif : un programme est une suite d’instructions qui font évoluer des variables.
— langage fonctionnel : les fonctions sont des valeurs « comme les autres ».
— langage orienté objet : modélisation des données sous forme d’objets qui ont des propriétés et
des opérations.
Le logiciel de programmation Python est libre et accessible à l’adresse www.python.org. Vous uti-
liserez en TP, sous windows, l’environnement de développement pyzo que vous pouvez télécharger
gratuitement sur la page web http ://www.pyzo.org/downloads.html.

2. Un paradigme de programmation est un style fondamental de programmation informatique qui explique la manière
dont les solutions aux problèmes doivent être formulées.
2.2. VARIABLES ET AFFECTATIONS 11

Il y a deux façons de programmer en python : l’utilisation interactive où l’on écrit les instructions
dans une console (appelée aussi shell ou terminal) Python, ou on peut lancer un programme (ou script)
enregistré dans un fichier texte suffixé par .py.
La console Python et la fenêtre de l’environnement de développement se présentent de la façon
suivante :

À gauche, les fichiers dans lesquels vous écrivez vos scripts, en haut à droite, les différentes docu-
mentations et en bas à droite la ou les consoles Python.
La documentation officielle en ligne de Python : www.python.org/doc/.

2.2 Variables et affectations


2.2.1 Affectations

Définition 2.2.1
1. Une variable permet de stocker des données pour les réutiliser ensuite.
2. Une affectation (ou assignation) crée une liaison entre un nom et une donnée. Les données
sont aussi appelée les valeurs.

Exemple 2.2.2
En Python, l’affectation se fait avec l’opérateur « “ ». Pour affecter la donnée 1 à la variable a,
on écrit a=1.

Exemple 2.2.3
Voici quelques exemples de types de données que l’on étudiera en détail par la suite. Pour connaitre
le type (ou la classe) d’un objet, on utilise la fonction type.
— Un entier : 2
— Un nombre à virgule flottante : 3.14
12 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

— Un nombre complexe : 4j (pour le nombre imaginaire on écrit 1j)


— Une chaîne de caractères : ’Mpsi’ ou " L’eau ".
— Une liste d’objet : [0, 3.14 , ’MPSI’].

Remarque 2.2.4
Pour supprimer une variable, on utilise l’instruction del.

Remarque 2.2.5
Le nom d’une variable (et aussi de fonction, d’une classe etc . . . ) doit respecter les règles syn-
taxiques suivantes :
1. Elle peut contenir des lettres, des chiffres, des underscore « _ », mais doit commencer par
une lettre.
2. La casse est importante : ma_variable ‰ Ma_VaRiAbLE.
3. Certains noms sont réservés par le langage : and, del, from, not . . . .

Remarque 2.2.6
On peut effectuer plusieurs affectations simultanément grâce au instructions suivantes :
1. a=b=1.
2. a, b, c = 2, 3, [2,5].

Précisons un peu ce qu’il se passe lord d’une affectation dans Python. On peut considérer que la
mémoire est divisée en deux parties : la table des symboles et la table des valeurs.
1. Les valeurs des différentes variables sont stockées dans la table des valeurs. Caque valeur possède
alors une adresse, qui est un nombre entier.
2. Dans la table des symboles, sont stockés les noms des variables auxquels on associe un type et
une adresse correspondant à la valeur de ces variables.
On peut résumer la situation par le schéma donné par la figure ci-dessous.

Figure 2.1 – Affectation

La fonction id permets d’obtenir l’adresse de la valeur d’une variable. Observons quelles situations
importantes.
1. Une valeurs peut être pointée par plusieurs noms de variables.
>>> a = 1
>>> b = a
>>> b, id(b), id(a)
(1, 7700768 , 7700768)
2. On peut écraser la valeur d’une variable par une autre.
2.2. VARIABLES ET AFFECTATIONS 13

>>> a = 1
>>> b = a
>>> a=2
>>> a, b, id(a), id(b)
(2, 1, 7700609 , 7700768)

3. Il faut être prudent lorsqu’une valeur est étiquetée par deux noms de variable.
>>> a = [1,2,3]
>>> b = a
>>> a[1]=0
>>> b
[1,0,3]

Définition 2.2.7
Une expression est une combinaison de variables et de littéraux a par l’intermédiaire d’opérateurs
et de fonctions.
a. Un littéral est une valeur écrite dans le programme. Il est d’un type donné qui détermine ce qu’il représente.

Remarque 2.2.8
1. Python évalue toujours les expressions. Pour répondre à l’instruction :

a=(5+int(3.7))/2,

Python évalue l’expression de droite puis il affecte la valeur trouvée, c’est-à-dire 4, à la


variable a.
2. Plusieurs instructions sur une même ligne de commande sont séparées par « ; ». Par exemple,
on peut écrire :
3+2; 3*4; 5/2; 2**3; 7//3; 7%3
Ces instructions correspondent aux opérations somme, produit, division, puissance, quotient
de la division entière, reste de la division entière.
3. Pour afficher la valeur de la variable test, on peut entrer les instructions test ou print(test).
On notera qu’il existe une différence entre ses deux instructions.
4. L’affectation d’une variable en informatique ne se comporte pas comme en mathématiques.
En effet, on peut écrire en informatique :

x = x+1 (x Ð x ` 1 en pseudo-langage).

Dans cette instruction, l’ordinateur évalue la valeur de x+1 puis il affecte cette nouvelle
valeur à la variable x.

On termine cette section en donnant trois méthodes pour échanger les valeurs de deux variables.
On suppose que a et b sont deux variables.
1. Il faut faire attention à ne pas écraser la valeur d’une variable existante sans enregistrer sa valeur.
Pour échanger les valeurs des variables a et b, on peut :
>>> c=a
>>> a=b
>>> b=c
2. Pour échanger les valeurs des variables a et b, on peut effectuer des opérations mathématiques :
14 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

>>> a=a+b
>>> b=a´b
>>> a=a´b
3. Enfin, une affectation parallèle permet de changer simultanément les valeurs des variables :
>>> a, b = b, a

2.2.2 La structure conditionnelle


L’expression a ě 0 est une variable booléenne.

Définition 2.2.9
Une expression est dite booléenne lorsqu’elle ne peut prendre que les deux valeurs True (Vrai) ou
False (Faux).

Voici quelques exemples qui permettent de construire des expressions booléennes :


— x == y : x est égal à y.
— x != y : x n’est pas égal à y.
— x > y : x est strictement plus grand que y.
— x < y : x est strictement plus petit que y.
— x >= y : x est plus grand ou égal à y.
— x <= y : x est plus petit ou égal à y.
— x is y : id(x) == id(y).
— x in y : x appartient à y (si y est une chaine de caractères ou une liste).
On a également la possibilité de combiner des variables booléennes à l’aide des opérateurs booléens
or, and et not.
>>> x = ´1
>>> (x > ´2) and (x ∗∗ 2 < 5)
True
>>> (x <= ´2) or x/0 # o p é r a t e u r s b o o l é e n s p a r e s s e u x
False
>>> not(x >= ´2)
False
>>> ´2 < x <= 0
True
Pour coder une instruction qui opère une disjonction de cas, on a besoin de l’instruction de choix
introduite par le mot clé if. La syntaxe est la suivante :
>>> if x >= 0:
... print (’variable positive ’)
... else :
... print (’variable négative ’)
Ce programme donne la valeur absolue de la variable x préalablement assignée. Lorsque la condition
x ě 0 est vérifiée, on demande de retourner la valeur de x, dans le cas contraire, on donne ´x. On
remarque qu’après les « : » le prompt « ąąą » est remplacé par « . . . », cela signifie que l’interpré-
teur attend obligatoirement d’autres instructions. Enfin, lorsque la définition de la fonction ou de la
procédure est terminée, on laisse une ligne vide.

Remarque 2.2.10
Dans Python, l’indentation est syntaxique ! En effet, les lignes d’un même bloc d’instructions
doivent être aligné verticalement. On utilise généralement la touche « tabulation », configurée sur
2.2. VARIABLES ET AFFECTATIONS 15

quatre espaces, pour dissocier les blocs.

>>> if a > 1:
... print (’le nombre est plus grand que 1’)
... if a <= 100:
... print (’Et il est plus petit que 100’)
... else :
... print (’le nombre est grand ’)
... print ("Difficile d’en dire plus !")
... else :
... print (’le nombre est plus petit que 1’)
Lors d’un choix multiple, on peut utiliser le mot clé elif, qui est la concraction de if et else.
C’est une syntaxe très utile pour effectuer une disjonction de cas lorsqu’il y a plus de deux issues. Par
exemple :
>>> if a > 0:
... print (’a est strictement positif’)
... elif a < 0:
... print (’a est strictement négatif’)
... else :
... print (’a est nul’)
Ce programme a aussi la syntaxe suivante :
>>> if a > 0:
... print (’a est strictement positif’)
... else :
... if a < 0:
... print (’a est strictement négatif ’)
... else :
... print (’a est nul’)
16 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

2.3 Les boucles


Les boucles sont des instructions itératives qui permettent d’exécuter à plusieurs reprises un bloc
d’instructions. Il existe deux types de répétitions : les conditionnelles et les inconditionnelles.

2.3.1 L’instruction while


Les répétitions conditionnelles commencent par le mot clé while suivi de la condition d’entrée
dans la boucle. Donnons un exemple de boucle conditionnelle :
n = 1
while n <= 5:
n = n+1
print (’Passage numéro ’, n)
print (’Il y a eu ’,n,’ passages dans la boucle ’)
La condition d’entrée dans la boucle est toujours une expression booléenne, ici n<=5. Initialement
la valeur de n est 1, donc la valeur de l’expression n<=5 est True. On dit que la condition d’entrée
dans la boucle est vérifiée.
Le bloc d’instructions à répéter, appelé le corps de la boucle, commence après les « : » et est
délimité par l’indentation. Ce bloc d’instruction sera exécuté de façon répété tant que les variables du
programme vérifie la condition d’entrée.
Lorsque la condition d’entrée n’est plus satisfaite, la procédure s’arrête et on dit qu’on sort de la
boucle ou que la boucle termine. Dans notre exemple, à chaque répétition (on dit aussi itération) du
corps de la boucle, la valeur de n augmente de 1 (on dit que la variable n est incrémentée). Donc, la
boucle se termine lorsque n vaut 6. Il y a eu 5 passages dans la boucle.

Remarque 2.3.1
Il existe une méthode format qui permet d’insérer les valeurs de variable dans une chaine de
caractère. Par exemple, l’instruction print(’Il y a eu ’,n,’ passages dans la boucle’)
peut être remplacée par print(’Il y a eu {} passages dans la boucle’.format(n)). La
méthode format est utilisable pour plusieurs variable. Par exemple, si a et b sont deux variables
d’un programme, on peut écrire :

"on peut insérer les valeurs {} et {} dans une chaine".format(a,b).

Il faut faire attention de ne pas créer des boucles infinies. Il est toujours possible d’interrompre
un programme qui boucle indéfiniment dans Python. Voici deux exemples de boucle qui ne terminent
pas :

1. n = 1
while n != 0:
n=n+1
print (’boucle infinie’)

while True :
print (’boucle infinie’)

On peut arrêter de force une boucle à l’aide de l’instruction break. On procède de la façon sui-
vante :
n=1
while True :
if n <10:
break
else :
2.3. LES BOUCLES 17

print (’passage numero ’, n)


n=n+1
print (’la boucle est terminée ’)
Cette boucle devrait être infinie puisque la condition d’entrée est toujours vraie. Mais l’instruction
break met fin à la procédure si n atteint 10, ce qui est le cas puisque la variable n est incrémentée à
chaque passage dans la boucle.

Remarque 2.3.2
2. En python, on peut remplacer l’instruction n=n+1 par n+=1. De même, les instructions n=n+3,
n=n-4, n=3*n, n=n**2 et n=n/5 s’écrivent aussi n+=3, n-=4, n*=3, n**=2 et n/=5 respectivement.

Donnons deux autres exemples de boucle conditionnelle :


1. Le programme suivant renvoie la somme des carrés des 100 premiers entiers.
n=1
S=0
while n <=100:
S=S+n ∗∗ 2
n=n+1
print (S)

2. Le programme ci-dessous donne le plus petit entier naturel n tel que 1 ` 23 ` ¨ ¨ ¨ ` n3 ě M , pour
M “ 104 .
M =10 ∗∗ 4
n=1
S=1
while S<M:
n=n+1
S=S+n ∗∗ 3
print (n)
On peut aussi écrire :
M =10 ∗∗ 4
n=1
S=0
while S<M:
S=S+n ∗∗ 3
n=n+1
print (n ´1)

2.3.2 Les boucles for


La fonction range est un itérateur d’entiers, elle permets de générer une suite d’entiers au fur et à
mesure des besoins, dans un soucis d’optimisation de la mémoire. La commande range(n) ne renvoie
pas une liste d’entier, mais génère les entiers de 0 à n ´ 1 (n est exclu). L’expression range(n) possède
un type particulier, le type range. Plus généralement, range(n,p) parcourt les entiers de n à p ´ 1K
et range(n,p,k) parcourt les entiers compris entre n inclus et p ´ 1 exclu, avec un pas de k.
On peut transformer un certain nombre d’objet Python en liste avec la fonction list. Par exemple,
Python donne les résultats suivants :
>>> list (range (6))
[0, 1, 2, 3, 4, 5]
>>> list (range (2, 6))
18 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

[2, 3, 4, 5]
>>> list (range (1, 8, 2))
[ 1, 3, 5, 7]
>>> list (range (9, 0, ´1)
[9, 8, 7, 6, 5, 4, 3, 2, 1]
Les boucles for sont des boucles inconditionnelle qui permettent de répéter un bloc d’instructions
n fois, où n est un entier déterminé à l’avance. La syntaxe d’une telle structure est la suivante :
n=5
for k in range (n):
print (k)
Les boucles for peuvent être utiliser avec d’autres objets pouvant être itérés. Par exemple, les
chaines de caractère et les listes sont des objets itétables. Voici deux exemples d’utilisation de l’ins-
truction for :
1. Avec une liste.
L = [2, 3.14 , ’deux ’, ’pi ’ ]
for l in L:
print (l)
2. Avec une chaine de caractère.
for l in ’mathématiques ’:
print (l)
On donne maintenant une autre version du calcul de la somme des carrés des 100 premiers entiers.
n=100
S=0
for i in range (1,n+1):
S=S+i ∗∗ 2
2.4. FONCTIONS, MÉTHODES ET MODULES 19

2.4 Fonctions, méthodes et modules


2.4.1 Les fonctions
Le langage Python possède un grand nombre de fonctions primitives, c’est-à-dire des programmes
déjà présents dans le code. On a rencontré certaines de ses fonctions comme id(), type() et print(). On
peut définir nos propres fonctions. Par exemple, pour définir une fonction mathématique on écrit :
>>> def f(x):
... return x ∗∗ 2
La commande return est utilisée pour définir des fonctions dont les résultats ont pour vocation
à être réutilisés. En effet, si l’on remplace l’instruction return x**2 par print(x**2) la fonction
produit visuellement le même résultat. En revanche, la fonction print() renvoie un objet de type None
qui n’est pas réutilisable. L’exemple suivant illustre ces différences :
>>> def g(x):
... print (x ∗∗ 2+3 ∗ x ´5)

>>> g(2) + g(3) # Ce c a l c u l r e n v o i e u ne e r r e u r


Une autre force de l’instruction return est qu’elle provoque l’abandon du programme après avoir
exécuté la fonction. Ainsi, toute instruction placée après n’est pas lue par l’interpréteur, on dit que
c’est du code mort.
def g(x,y):
return x ∗∗ 2 ´ y ∗∗ 2
print (’Ne sera jamais lu’)
Il est préférable d’écrire vos fonctions dans un script, c’est-à-dire dans un fichier text.py pour les
réutiliser par la suite.
Une fonction booléenne, appelée aussi prédicat, est une fonction qui renvoie un booléen en résultat.
def f(x):
if x == 0:
return True
else :
return False
Il est possible de créer des fonction sans argument :
>>> def hi ():
... print (’Bonjour ’)

>>> hi()
Bonjours
Dans certains programmes, on a besoin d’interagir avec l’utilisateur. La fonction input() permet
de demander à l’utilisateur d’entrer une valeur qui pourra être utilisée au cours de la procédure.
>>> x = input ()
’Quoi ?’ # L ’ u t i l i s a t e u r r e n t r e u ne v a l e u r
>>> print (x)
Quoi ?
>>> x = input (’Donner un entier ’)
Donner un entier 6 # l ’ u t i l i s a t e u r entre 6
>>> x
’6’
>>> x = int(input (’Entrer un entier :’))
Enter un entier :6
>>> x
6
20 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

2.4.2 Les méthodes


Concernant les opérateurs prédéfinis dans Python, il faut différencier les fonctions et les méthodes.
Les fonctions sont des programmes qui peuvent prendre en argument des objets de différent type. Par
exemple, la fonction str() convertit un objet en chaine de caractères.
>>> str (6)
’6’
>>> str([0, 5])
’[0, 5] ’
Les méthodes sont des programmes qui s’appliquent seulement à des objets de types précis. Les
méthodes ont une syntaxe particulière.
>>> z = 1 + 3j
>>> z. conjugate ()
(1 ´3j)
On regarde à titre d’exemple la méthode .format(), qui concerne les chaines de caractères et qui
est très utile pour afficher les résultats d’un programme.
>>> x = 2
>>> n = 5
>>> ’On calcule {} ∗∗ 5 ’.format (x)
On calcule 2 ∗∗ 5
>>> ’{} calcule {} ∗∗ {} ’.format (’On ’, x, n)
On calcule 2 ∗∗ 5
Enfin, pour connaitre la syntaxe et le fonctionnement des fonctions et méthodes dans Python,
on utilisera la fonction help(). Pour connaitre les fonctions et méthodes qui s’appliquent à un objet
donné, on appellera la fonction dir(). En écrivant dir(1j), on trouve qu’il existe une méthode .real()
donnant la partie réelle du nombre complexe.

2.4.3 Les modules


Le langage Python contient de nombreux modules. Un module est un fichier text.py qui regroupe
des fonctions ou méthodes sur un thème donné. Pour utiliser ces fonctions ou méthodes primitives,
il faut importer en amont les modules en question. Par exemple, le module math contient un grand
nombre de fonctions usuelles mathématiques et des constantes remarquables telles que le nombre π.
Les différentes syntaxes possibles pour utiliser ces fonctions sont les suivantes :

1. >>> from math import pi , cos


>>> cos(pi /6)
0.8660254037844387
>>> pi
3.141592653589793
>>> dir(math )
On a importé uniquement le nombre pi et la fonction cosinus. On remarque également que python
ne fait à priori pas de calcul formel puisqu’il donne des valeurs approchées.

2. >>> import math


>>> dir(math ) # l i s t e des fonctions
>>> math .log(math .e)+ math .sqrt (2)
2.414213562373095
>>> import math as m
>>> m.fabs( ´5)
5
2.4. FONCTIONS, MÉTHODES ET MODULES 21

Ici, on importe tout le contenu du module math, mais il est plus commode d’ajouter le raccourci
as m.
3. >>> from math import ∗
>>> floor (4.6)
4
Le symbole ˚ signifie qu’on importe tous les noms des fonctions présentes dans le module. Mais
ceci n’est pas conseillé puisqu’il peut y avoir interférence avec les noms de vos propres fonctions
ou des fonctions dans d’autres modules.
On énumère quelques modules intéressants dont certains seront développés plus tard dans ce cours :
— random : générer des nombres aléatoires.
— time : fonction clock qui permet de mesurer des temps d’exécution.
— Autre : turtle, sys, os, matplotlib, fraction, décimal etc . . .

Complément sur les fonctions


Pour qu’une fonction renvoie une fonction en résultat, on utilise une fonction anonyme introduite
par le mot clé lambda. Pour définir la composée de deux fonctions quelconques, on procède de la façon
suivante :
def composition (f,g):
return lambda x: f(g(x))
On peut introduire une documentation dans notre fonction qui sera alors accessible vie la fonc-
tion help(). La documentation est importante pour qu’un utilisateur extérieur comprenne comment
l’utiliser. La syntaxe est la suivante :
def composition (f,g):
" " " R e n v o i e l a composée de deux f o n c t i o n f et g .

>>> f r o m math i m p o r t s i n , cos


>>> f = c o m p o s i t i o n ( cos , sin )
>>> [ f ( x ) f o r x in range (3)]
[1.0 , 0.6663667453928805 , 0.6143002821164822]
"""
return lambda x: f(g(x))
22 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

2.5 Structures de données


2.5.1 Les chaines de caractères
Les éléments d’une chaine de caractères 3 , comme ceux d’une liste, sont indexés. Le premier étant
d’indice 0. Une chaine de caractère n’est pas un objet modifiable, l’instruction chaine[2] = 3 pro-
voque une erreur. On peut toujours extraire des sous-chaines de caractères et obtenir la longueur d’une
chaine de caractères.
>>> c = ’une chaine de caractères ’
>>> c[0], c[2], c[3], c[ ´1]
(’u’, ’e’, ’ ’, ’e’)
>>> len(c)
23
>>> c [4:10]
’chaine ’
Les opérateurs ˚ et ` permettent respectivement de faire la concaténation de deux chaines et de
répéter une chaine.
>>> ’conca ’ + ’ténation ’
’concaténation ’
>>> ’Hop ! ’ ∗ 3
’Hop ! Hop ! Hop !’
On a déjà vu qu’il était possible de parcourir les caractères d’une chaine grâce au mot clé for.
>>> c = ’mathématiques ’
>>> for lettre in c:
... print ( letter + ’ ∗ ’, end = ’ ’)

m ∗ a ∗ t ∗ h ∗ é ∗ m ∗ a ∗ t ∗ i ∗ q ∗ u ∗e ∗ s ∗
On peut aussi écrire ce programme à l’aide d’une boucle while :
>>> c = ’mathématiques ’
>>> index = 0
>>> while index < len(c):
... print ( c[index ] + ’ ∗ ’, end = ’ ’)

m ∗ a ∗ t ∗ h ∗ é ∗ m ∗ a ∗ t ∗ i ∗ q ∗ u ∗e ∗ s ∗

2.5.2 Les listes (suite)

Définition 2.5.1
Une liste est un ensemble de données dans lequel chacune des données est repérée par un indice.

On écrit une liste de la façon suivante :


Tous les éléments d’une liste sont directement accessibles par son indice. L’indexation d’une liste
en Python commence par 0. Pour obtenir le premier élément de la liste liste, on écrira liste[0], pour
le second liste[1]. Le terme d’indice i est donné par l’instruction liste[i]. On peut également
obtenir directement le dernier élément de la liste avec liste[-1]. De même, pour l’avant-dernier, on
écrit liste[-2] etc . . .
Il est commode de raisonner à l’aide des virgules séparant les termes de la liste pour comprendre
ces indices.
Les listes sont des objets Python modifiables, on dit aussi qu’ils sont mutables.
3. Chaque caractère possède son équivalent en code numérique : c’est le code ASCII (American Standard Code for
Information Interchange)
2.5. STRUCTURES DE DONNÉES 23

>>> liste = [1, 3, 14, 15]


>>> liste [2] = ’New’
>>> liste
[1, 3, ’New’, 15]
La fonction len(), de l’anglais length, permet de connaître la longueur d’une liste. Il est possible
d’extraire une sous-liste d’une liste.
>>> list = [1, 2, 3.14 , True , ’Ho !’]
>>> len(list )
5
>>> sous_list1 = list [1:4]
>>> sous_list1
[2, 3.14 , True ]
>>> list [:3]
[1, 2, 3.14]
>>> list [3:]
[True , ’Ho !’]
>>> list [:]
[1, 2, 3.14 , True , ’Ho !’]
Si la liste est de longueur 5, l’instruction liste[5] génère une erreur.
On a déjà vu plusieurs opérations sur les listes. Les opérateurs ` et ˚ fonctionnent sur les listes de
la même façon que pour les chaines de caractères. On a aussi vu comment extraire une sous-liste, c’est
aussi le principe de « découpage en tranches » (slicing). Cette technique permet de modifier, fusionner
ou effacer des listes de façon très confortable.
>>> l1 = [ 0, 6, 4, 4, 3, 6, 0, 0, 1, 1]
>>> l2 = ["c’est", ’un ’, ’numéro ’]
>>> l1 + L2
>>> l1 [4:9] = []
>>> l1
[0, 6, 4, 4]
>>> l2 [2] = [’de ’, ’téléphone ’]
>>> l2
["c’est", ’un ’, ’numéro ’, ’de ’, ’téléphone ’]
La méthode append() permet de rajouter un élément à la fin de la liste.
>>> liste = [3.14 , 7, ’G’]
>>> liste . append (5)
>>> liste
[3.14 , 7, ’G’, 5]
Quelques méthodes utiles concernant les listes :
— list.extend(L) : ajoute à la fin les éléments de L.
— list.insert(i,x) : insert l’élément x en position i.
— list.pop(i) : supprime l’élément d’indice i et le renvoie (ce qui peut se faire avec l’instruction
del list[i], mais ceci ne retourne pas l’élément).
— list.index(x) : renvoie l’indice de la première occurrence de x.
24 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

— list.count(x) : renvoie le nombre d’occurrences de x.


— list.sort() : trier une liste de nombres.
— list.reverse() : renverser l’ordre des éléments.
Les boucles for permettent également de définir des listes par compréhension. Voici quelques
exemples :
>>> liste = [ 2, 3, 5, 7, 11]
>>> [2 ∗∗ i for i in liste ]
[4, 8, 32, 128, 2048]
>>> [ [x, x ∗∗ 2] for x in liste ]
>>> [d for d in range (1 ,101) if 100 % d == 0]
[1, 2, 4, 5, 10, 20, 25, 50, 100]
>>> liste_2 = [3, 5, 7, 10, 10]
>>> [ i ∗ l for i in liste for l in liste_2]

2.5.3 Les tuples


Un tuple est une collection d’objets séparés par des virgules. Un tuple se comporte comme les
chaines de caractères, ce sont des objets non modifiables. Lorsqu’on veut être sûr que notre objet ne
soit pas modifié par erreur au cours du programme, on préférera l’utilisation des tuples par rapport
aux listes. Les tuples sont également moins gourmands en mémoire puisqu’ils ne sont pas mutables.
Voici quelques exemples de syntaxe et de fonctionnement :
>>> tup = (’a’, ’b’, ’c’, 1, 2, 3, True , False )
>>> len(tup)
8
>>> tup [2 : 4]
(’c’, 1)
>>> (’Andrée ’,) + tup
>>> tup1 , tup2 = (2, 3), (4, 5, 6)
>>> tup ∗ 3 + tup2
(2, 3, 2, 3, 2, 3, 4, 5, 6)
>>> for e in tup:
... prin(e, end = ’ : ’)

a : b : c : 1 : 2 : 3 : True : False :
>>> 5 in tup
False
On note qu’il n’est pas possible d’utiliser l’instruction del ou la méthode remove() par exemple.

2.5.4 Les dictionnaires


Les dictionnaires sont des objets mutables, comme les listes, mais leurs éléments sont accessibles
par un index non ordonné et plus général que celui des listes. Les valeurs de cet index seront les clés.
>>> dico = {} # d i c t i o n n a i r e v i d e
>>> dico[’computer ’] = ’ordinateur ’
>>> dico[’keybord ’] = ’clavier ’
>>> dico[’mouse ’] = ’souris ’
>>> dico
On peut effectuer des tests d’appartenance sur les dictionnaires.
>>> invent = {’pomme ’ : 234, ’poire ’ : 120, ’ananas ’ : 67}
>>> len(invent )
3
2.5. STRUCTURES DE DONNÉES 25

>>> if ’pomme ’ in invent :


... print (’Nous vendons des pommes .’)
... else :
... print (’Nous ne vendons pas de pommes .’)

Nous vendons des pommes .


Il est aussi possible d’accéder soit à l’ensemble des clés, soit à l’ensemble des valeurs, soit aux couples
clé-valeur du dictionnaire grâce respectivement aux méthodes keys(), values() et items().
>>> invent = {’pompe ’ : 234, ’poire ’ : 120, ’ananas ’ : 67}
>>> invent .keys ()
dict_keys ([ ’pommel ’, ’poire ’, ’ananas ’])
>>> list (invent .values ())
[234 , 120, 67]
>>> tuple ( invent .items ())
(( ’pomme ’, 234) , (’poire ’, 120) , (’ananas ’, 67))
>>> for k in invent .keys ():
... print (’Il reste {} {}(s)’.format ( invent [k], k))

Il reste 234 pomme (s)


Il reste 120 poire (s)
Il reste 67 ananas (s)
Les clés ne sont pas nécessairement des chaines de caractères. En revanche, les clés doivent être
des objets non modifiables. Les tuples sont autorisés mais pas les listes.
26 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

2.6 Compléments d’algorithmique


Vérifier la correction (ou la validité) d’un algorithme consiste à montrer qu’il renvoie bien le ré-
sultat souhaité. Il est important de s’assurer aussi de sa terminaison, c’est-à-dire qu’il ne boucle pas
indéfiniment, lorsqu’il contient des boucles conditionnelles.

2.6.1 Prouver un algorithme


Les boucles sont des structures itératives. Un programme est dit itératif s’il utilise de telles ins-
tructions.

Définition 2.6.1
Les structures ou instructions itératives sont des instructions qui permettent de répéter un certain
nombre de fois une série d’instructions simples ou composées constituant un bloc.

Définition 2.6.2
Un invariant est une propriété logique sur les valeurs des variables qui caractérisent tout ou partie
de l’état interne du programme et qui doit être « toujours » vraie. Dans le cas d’un programme
itératif, l’invariant est l’l’invariant de boucle.

Définition 2.6.3
On appelle invariant de boucle un prédicat sur les arguments de la boucle qui doit être vraie
avant et après chaque passage dans la boucle.

Un programme itératif est structuré de la façon suivante :


1. On initialise les variables. Les états des variables avant la boucle constituent les pré-conditions
E (ou conditions d’entrée). Si les conditions d’entrée vérifient l’invariant de boucle I, alors le
programme entre dans la boucle.
2. La boucle va se répéter un certain nombre de fois (tant que les conditions vérifient l’invariant,
si « I ^ condition » est vrai). Si les conditions (qui sont les états des variables) ne vérifient plus
l’invariant (on a « I ^ non(condition) » qui est vraie). Le programme sort de la boucle.
3. En sortie de boucle les valeurs des variables sont les post-conditions S (ou conditions de sortie).
Les post-conditions doivent correspondre au résultat souhaité.
Le résultat du programme doit être un cas particulier de l’invariant de boucle. Ainsi, trouver un
invariant de boucle revient à démontrer la correction du programme. En générale, on démontre que le
prédicat est un invariant de boucle par récurrence.
On étudie le programme suivant qui calcule la factorielle de n.
def fact1 (n):
res = 1
for k in range (1,n +1):
res = res ∗ k
return res
On note I le prédicat suivant :

Après la k-ème itération (après le k-ème passage dans la boucle), la valeur de res est égale à k!.

En effet, pour la condition initiale (res “ 1 “ 0!) la propriété est vraie (pas encore de passage
dans la boucle). Supposons qu’elle est vraie après le k-ème passage dans la boucle, avec k ă n.
Par hypothèse de récurrence, on a res “ k!, et lors du k ` 1-ème passage la variable res devient
2.6. COMPLÉMENTS D’ALGORITHMIQUE 27

Figure 2.2 – I est l’invariant de boucle

res “ k! ˆ pk ` 1q “ pk ` 1q!, d’où la propriété au rang k ` 1. Ce qui prouve l’invariant pour tout k
dans J1, nK (il y a exactement n passages dans la boucle). Une fois la boucle terminée (elle s’arrête
nécessairement puisqu’elle est inconditionnelle) on obtient res “ n! (la boucle termine après la n-ème
itération), ce qui est bien le résultat cherché.
On donne une autre version de ce programme :
def fac2(n):
i = n
res = 1
while i > 0:
res = res ∗ i
i = i ´ 1
return res
Un invariant de boucle est « on a toujours res ˆ i! “ n! ».
On ne démontrera pas systématiquement l’invariant de boucle, mais il est souhaitable de le mettre
en commentaire dans le programme lorsque que celui-ci est itératif.
On s’intéresse à la somme des termes d’une liste de nombres.
def somme (L):
k = 0
s = 0
while k < len(L):
s = s + L[k]
k += 1
#I n v a r i a n t : s = somme p o u r i d e 0 à k d e s L [ i ]
return s
k
ÿ
L’invariant est le suivant s “ Lris. C’est évident pour les valeurs initiales des variables s et k. A
i“0
chaque passage dans la boucle, k est incrémenté de 1 et on ajoute à s le terme Lrks. La récurrence est
lenpLq´1
ÿ
immédiate et après le dernier passage dans la boucle, la valeur de k est lenpLq´1, ainsi s “ Lris
i“0
ce qui est le résultat attendu.
On cherche à fournir le quotient et le reste de la division euclidienne de deux entiers. Des erreurs
se sont glissés dans le programme ci-dessous. Les corriger en étudiant l’invariant de boucle. Puis
démontrer la terminaison et la correction de l’algorithme.
28 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

def division_successive (a,b):


if a < b:
return 0, b #D i v i s i o n d e a p a r b
else :
q = 1
r = a
while r >0:
q +=1
r = r´b
# Invariant : a = q ∗ b+r
return q, r
On considère la programme mystere suivant :
def mystere(L,x):
n=len(L)
a=False
k=0
while not(a) and k<n:
if x=L[k]:
a=True
k+=1
return a
Répondre aux questions suivantes :
1. Donner les types possibles des variables d’entrée du programme et le justifier.
2. Que fait le programme ?
3. Démontrer la terminaison du programme mystère.
4. Donner un invariant de boucle et le démontrer.
5. Écrire le programme d’une autre façon.
2.6. COMPLÉMENTS D’ALGORITHMIQUE 29

2.6.2 Complexité d’un algorithme


Après avoir démontré la correction puis la terminaison d’un programme, on peut s’interroger sur
son efficacité. Le domaine informatique qui traite de ce sujet est appelé la complexité.
Il y a deux types de complexités : la complexité temporelle qui mesure la rapidité du programme
à résoudre le problème et la complexité spatiale qui évalue les proportions de la mémoire utilisée.
On va s’intéresser principalement à la complexité temporelle. Cette complexité dépend de la taille
des données et de la structure du programme. La complexité peut se mesurer en donnant l’ordre
de grandeur du nombre d’opérations élémentaires (affectations, évaluations, calculs simples etc . . . )
effectuées par le programme en fonction de la taille des données. Un entier n est associé à la taille des
données.

Exemple 2.6.4
Donnons quelques exemples de taille de donnée :
1. Une chaine de n caractères ou une liste de n éléments sera une donnée de taille n.
2. Un tableau à n lignes et p colonnes sera une donnée de taille np.
3. La taille d’un entier n peut être donnée par son nombre de chiffres à savoir tlog2 pnqu, où
log2 est le logarithme en base 2.
4. Un nombre décimal peut être caractérisé par son exposant et la taille de sa mantisse (voir
le chapitre sur la représentation des nombres en machine).

def compte (n):


for i in range (n):
print (i, end = ’, ’)
Ce programme affiche, sur une même ligne, les entiers de 0 à n ´ 1. La taille des données correspond
à l’entier n lui-même et la complexité du programme est de l’ordre n (exactement n passages dans
la boucle et on considère que la fonction print() effectue une opération élémentaire. On dit que le
programme a un coût de l’ordre de n, on note Θpnq la complexité de celui-ci.
Si pvn q et pun q sont deux suites, la notation un “ Θpvn q, qui se lit « un est un grand thêta de vn »,
signifie que les deux suites ont le même ordre de grandeur, plus précisément, on a :

Définition 2.6.5
un “ Θpvn q si, et seulement si, il existe c ą 0 tel que :
1
un ď vn ď cun , @n P N.
c

Les ordres de grandeur de complexité les plus importants sont les suivants :
— logarithmique : de l’ordre de lnpnq,
— linéaire : de l’ordre de n,
— quasi-linéaire : de l’ordre de n lnpnq,
— quadratique : de l’ordre de n2 ,
— polynomial : de l’ordre de nk , pour un entier k ě 2,
— exponentiel : de l’ordre de an , où a ą 1.
La complexité peut également dépendre de la nature des données. Par exemple, il est très facile de
savoir que 243112609 n’est pas premier alors que c’est difficile pour 243112609 ´ 1 qui sont pourtant des
entiers de taille équivalente. C’est pourquoi, il est courant de mesurer la complexité d’un programme
en moyenne mais aussi dans le pire des cas.
L’algorithme de recherche d’un élément dans une liste est le suivant :
def trouv (x,L):
res = False
30 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE

for i in range (len(L)):


if x = L[i]:
return True
return False
La complexité dans le pire des cas est Θpnq, où n est la longueur de la liste. En effet, dans le pire des
cas, x n’est pas dans la liste et on parcoure tous les éléments de la liste.
La fonction suivante permet de calculer n! :
def fact(n):
f=1
for k in range (1,n +1):
f=f ∗ k
return f
n
ÿ 1
On va utiliser cette fonction pour calculer la somme :
k“0
k!

def som1(n):
s=0
for i in range (n+1):
s=s+fact (i)
return s
On donne une autre algorithme pour calculer la somme :
def som2(n):
s=1
f=1
for i in range (1,n +1):
s=s+f
f=f ∗ i
return s
Comparer le nombre de multiplications effectuées dans les algorithmes som1 et som2.
On donne deux algorithmes pour calculer un nombre a à une puissance entière n. La méthode
« naïve » est la suivante :
def puissance (a,n):
res = 1
for i in range (n):
res = res ∗ a
return res
Il est évident que cet algorithme a une complexité linéaire. On donne maintenant l’algorithme d’ex-
ponentiation rapide qui calcule aussi an . L’exponentiation rapide a pour but de calculer une puissance
entière d’un réel en faisant le moins de multiplications possibles. Soit a un réel et n un entier naturel.
2
On écrit n en base 2 : n “ dN ¨ ¨ ¨ d0 . On rappelle que les N chiffres de n dans son écriture en base 2
sont dans t0, 1u et n “ d0 ` d1 2 ` ¨ ¨ ¨ ` dN ´1 2N ´1 . On a 2N ´1 ď n ă 2N . Ainsi, on peut écrire :
N´1
an “ ad0 ˆ pa2 qd1 ˆ ¨ ¨ ¨ ˆ pa2 qdN´1 .

Par cette méthode, on effectue au plus N ˆ pN ´ 1q multiplications. On peut résumer cet algorithme
de calcul de la façon suivante :
n
#
n px2 q 2 si n est pair,
a “ n´1
xpx2 q 2 si n est impair.

Le tableau ci-dessous est l’exemple de a à la puissance 100.


2.6. COMPLÉMENTS D’ALGORITHMIQUE 31

Restes 1 1 a4 a4 a4 a4 ˆ a32 a4 ˆ a32 ˆ a64


Calcul des carrés a a2 a4 a8 a16 a32 a64
Reste de la division 100 50 25 12 6 3 1
On a alors le programme python correspondant :
def puissance_rapide (a,n):
q = n
reste = 1
puiss = a
while q > 1:
if q % 2 == 1:
reste = reste ∗ puiss
puiss = puiss ∗ puiss
q = q//2
# Invariant : a ∗∗ n = ( p u i s s ∗∗ q )∗ r e s t e
return reste ∗ puiss
1. Donner un invariant de boucle pour l’algorithme de puissance rapide et le démontrer.
2. Pour un nombre n à 11 chiffres, comparer le nombre de multiplications nécessaires aux algo-
rithmes de puissance rapide et naïve.
3. Quelles sont les complexités dans le pire des cas pour les deux méthodes ? On comptera le nombre
de passage dans la boucle dans le pire des cas et non le nombre de multiplications.
On termine par utiliser le module time pour illustrer les différences de temps d’exécution de pro-
grammes calculant une puissance entière.
a = 92982829
n = 50000
import time
t0 = time .clock ()
x = puissance (a,n)
t1 = time .clock ()
print (’{: >25} ´´> {} s’.format (’méthode naïve ’,t1´t0 ))
t0 = time .clock ()
y = puissance_rapide (a, n)
t1 = time .clock ()
print (’{: >25} ´´> {} s’.format (’fonction puissance_rapide ’,t1´t0))
Attention, les temps d’exécution dépendent du système d’exploration et de la machine qu’on utilise.
Que fait l’algorithme suivant ?
def algoA (N):
L = [True for i in range (N)]
L[0] = False
L[1] = False
i = 2
while i < N:
if L[i] == True :
j =2 ∗ i
while j < N:
L[j] = False
j = j+i
i +=1
print (L)
Établir la complexité de cet algorithme (on admettra que la somme des inverses des n premiers nombres
premiers est un Θplnplnpnqq).
32 CHAPITRE 2. INTRODUCTION À L’ALGORITHMIQUE
Chapitre 3

Quelques modules de Python et


applications

La documentation en ligne des modules numpy et scipy est accessible à l’adresse http ://docs.scipy.org/doc/.

3.1 Le module matplotlib


On peut trouver un grand nombre d’exemples d’utilisation du module matplotlib vers le lien
http ://matplotlib.org/gallery.html.

3.2 Les modules numpy et scipy


3.2.1 Présentation

3.3 Ingénierie numérique et simulation


3.3.1 Équations algébriques
3.3.2 Équations différentielles
3.3.3 Système linéaire

3.4 Lire et écrire dans un fichier

33
34 CHAPITRE 3. QUELQUES MODULES DE PYTHON ET APPLICATIONS
Chapitre 4

Initiation aux bases de données

Sommaire
4.1 L’algèbre relationnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.1.1 Formalisme de l’algèbre relationnelle . . . . . . . . . . . . . . . . . . . . . . . . 35
4.1.2 Création d’une base de données . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2 Opérateurs sur le modèle relationnel . . . . . . . . . . . . . . . . . . . . . . 39
4.2.1 Projection et sélection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2.2 Produit cartésien et jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.3 Requêtes SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3.1 Requêtes d’agrégation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

On souhaite mettre en place un système en ligne pour recueillir les notes orales des élèves de MPSI.
On peut stoker ces données sous forme de tableau :
Notes =[( ’Prof1 ’, [(15 , ’élève1 ’, ’semaine1 ’),
(10, ’élève2 ’,’semaine1 ’)]),
(’Prof2 ’ ,[(9, ’élève3 ’,’semaine1 ’),
(11, ’élève4 ’,’semaine1 ’)]]
Cette façon de stoker les données est commode pour trouver les notes données par chaque colleur.
En revanche, la recherche de la liste des élèves ayant eu une note inférieure à 10 peut avoir un coût
en temps important. Les bases de données relationnelles vont répondre de manière efficace à notre
problème.
Le problème de certains choix de stockage de données est la redondance des informations enregis-
trées. La base de donnée représentée par le tableau suivant possède cette inconvénient.
Semaine Professeur Groupe Elève Note
1 Vas 2 Lamp 15
1 Vas 2 Maz 8
1 Tour 7 Guy 15
2 Tour 5 Kat 11
2 Vas 7 Guy 10
2 Vas 2 Maz 12

4.1 L’algèbre relationnelle


4.1.1 Formalisme de l’algèbre relationnelle
L’idée est de structurer les données et les relations entre les données au seins de plusieurs tableaux.
Les tables « Elèves », « Notes » et « Colleurs », représentent les relations au seins de notre base de
données. L’ensemble des attributs est tid, nom, prénom, groupe, valeur, semaine, matiereu. Chaque
attribut possède un domaine de valeurs, par exemple les valeurs de l’attribut id sont des entiers.

35
36 CHAPITRE 4. INITIATION AUX BASES DE DONNÉES

(a) Elèves (b) Notes


id nom prénom groupe valeur nom semaine id
1 Maz Max 1 15 Vas 1 1
2 Maz Alex 1 13 Pat 1 2
3 Lamp Steevy 2 9 Ren 1 3
4 Kat Ben 2 8 Ren 1 4
5 Alsander Guy 3 17 Beg 1 5
6 Cad Juliette 3 20 Beg 1 6
12 Vas 2 1
14 Vas 2 2
16 Tour 2 3
17 Ren 2 4
15 Beg 2 5
12 Tour 2 6
(c) Colleurs
nom prénom matière
Vas Guillaume Maths
Ren Ange Maths
Beg Guillaume Maths
Pat Anna Lettres
Tour Stéphane Physique

Table 4.1 – Résultats oraux

On considère A un ensemble fini. Les éléments de A sont appelés des attributs. On se donne
également un ensemble D (fini ou infini) et une application dom : A Ñ PpDq. On pose
Di “ dompAi q, pour tout Ai P A. L’ensemble Di sont appelé le domaine de Ai .

Définition 4.1.1
Un schéma relationnel est un sous-ensemble S “ tA1 , . . . , An u de A.

Définition 4.1.2
Soit S “ tA1 , . . . , An u un schéma relationnel. On appelle relation ou table associée au schéma
relationnel S un sous-ensemble fini de D1 ˆ ¨ ¨ ¨ ˆ Dn . On note R ou RpSq cette relation.

Remarque 4.1.3
Les éléments d’une relation sont alors des n-uplets (nuplet ou « tuple » en anglais), où n est le
nombre d’attributs dans le système relationnel.

Définition 4.1.4
Soit RpSq une relation associée au schéma relationnel S. Les éléments de RpSq sont les valeurs
ou les enregistrement de la relation. On note 7RpSq le nombre d’éléments (ou cardinal) de RpSq.
4.1. L’ALGÈBRE RELATIONNELLE 37

Exemple 4.1.5
La table Notes est une relation dont le système relationnel est constitué des attributs valeur,
nom, semaine et élève (ce sont les colonnes de la table). Les lignes sont les enregistrements de la
relation.

Remarque 4.1.6
Pour e P RpSq, on pourra noter e.A la composante de e associée à l’attribut A. Si K Ă S, on
notera epKq les valeurs de e pour les attributs de K. Dans notre cas, si on note e3 la troisième
ligne de la table Élève, on a e3 pnom,groupeq “ tLamp,2u et e3 .id “ 3.

Définition 4.1.7
[Base de donnée] Une base de données est un ensemble de relations accompagnées de leurs sys-
tèmes relationnels.

(a) E1 (b) E2
id nom prénom groupe id nom prénom groupe
1 Maz Max 1 3 Lamp Steevy 2
4 Kat Ben 2 4 Kat Ben 2
5 Alsander Guy 3 5 Alsander Guy 3
(c) E1 X E2
id nom prénom groupe
4 Kat Ben 2
5 Alsander Guy 3

Proposition 4.1.8
Deux relations R1 et R2 associées au même système relationnel S sont des sous-ensembles finis de
D1 ˆ ¨ ¨ ¨ ˆ Dn , où les Di sont les domaines des attribues de S. On peut alors utiliser les opérateurs
ensemblistes sur les relations portant sur un même système relationnel S. Par exemple, R1 Y R2 ,
R1 X R2 et R1 zR2 (aussi noté R1 ´ R2 ) sont des relations associées à S respectivement appelées la
réunion, l’intersection et la différence.

4.1.2 Création d’une base de données


Soit RpSq une relation de système S.

Définition 4.1.9
[Clé] Soit K Ă S. On dit que K est une clé pour R si pour toutes valeurs e1 et e2 dans R telles
que e1 pKq “ e2 pKq, on a e1 “ e2 .

(d) E1 Y E2 (e) E1 ´ E2
id nom prénom groupe id nom prénom groupe
1 Maz Max 1 1 Maz Max 1
3 Lamp Steevy 2
4 Kat Ben 2
5 Alsander Guy 3

Table 4.2 – Opérations ensemblistes


38 CHAPITRE 4. INITIATION AUX BASES DE DONNÉES

Exemple 4.1.10
Dans la table « Elève », les attributs « nom, prénom » forment une clé. En revanche, l’attribut
« nom » seul n’est pas une clé.

Définition 4.1.11
[Clé primaire] Une clé primaire (ou identifiant) est une clé constituée d’un seul attribut.

Remarque 4.1.12
Soit RpSq une relation et A P S. Si A est une clé primaire, alors e ‰ e1 donne e.A ‰ e1 .A. En
d’autres termes, l’application suivante est injective :

pA : RpSq Ñ dompAq
e ÞÑ e.A

Exemple 4.1.13
Dans la table « Élève », l’attribut « id » est une clé primaire.

Exemple 4.1.14
Dans la table « Notes », il n’y a pas de clé primaire.

Remarque 4.1.15
Il est parfois pratique de rajouté un identifiant de type entier en tant qu’attribut qui jouera le
rôle de clé primaire.

Définition 4.1.16
[Clé étrangère] Une clé étrangère est l’attribut d’une relation dont le domaine est une clé primaire
d’une autre relation.

Exemple 4.1.17
Dans la table « Notes », les attributs « nom » et « id » sont tous les deux des clés étrangères.

Exemple 4.1.18
On considère les schémas relationnels donnés par les tables ??. On représente cette base de
données de la façon suivante :
Elèves(id, nom, prénom, groupes)
Colleurs(nom, prémon, matière)
Notes(valeur, 7 colleur, semaine, 7 élève)
Les clés choisies sont soulignées et les clés étrangères sont marquées d’un 7. On peut ajouter les
domaines des attributs :
INT : entier.
VARCHAR(n) : chaine de caractère d’au plus n caractères.
REAL, FLOAT
DATE . . .
4.2. OPÉRATEURS SUR LE MODÈLE RELATIONNEL 39

Exercice 4.1. On souhaite réaliser une base de données représentant les séances des films joués
dans différentes salles de cinéma. L’ensemble des attributs sera : titre, réalisateur, acteur, salle, co-
ordonnées, téléphone et horaire. Proposer un ensemble de schémas relationnels, de clés primaires et
étrangères permettant de réaliser cette base de données. Donner le domaine des attributs.
Exercice 4.2. On souhaite créer un atlas numérique des résultats sportifs aux Jeux Olympiques. La
base de données devra contenir :
Les dates, les villes et les différentes épreuves des Jeux Olympiques.
Les noms, nationalités et résultats des athlètes.
Proposer un ensemble de schémas relationnels, de clés primaires et étrangères permettant de réaliser
cette base de données.
Exercice 4.3. Une entreprise de vente de pièces automobiles souhaite informatiser sa gestion. La
base de données devra stocker les informations suivantes :
Les produits proposés, leur désignation, le prix unitaire et la quantité en stock.
Les différentes commandes passées, la date et son prix total.
Les noms et prénoms des clients, ainsi que leur(s) numéro(s) de téléphone.
Proposer un ensemble de schémas relationnels, de clé primaires et étrangères permettant de réaliser
la gestion des commandes de cette entreprise. Donner le domaine des attributs.

4.2 Opérateurs sur le modèle relationnel


On va définir des opérateurs élémentaires sur les ensembles de relations. Soit RpSq une relation de
schéma S. Les opérateurs permettent d’interroger la base de données en créant de nouvelles tables
contenant les informations souhaitées. On dit qu’on effectue une requête sur la base de données.

Définition 4.2.1
L’algèbre relationnelle est l’ensemble des relations, dont les systèmes sont des parties de A, muni
des opérateurs relationnels.

4.2.1 Projection et sélection

Définition 4.2.2
[Projection] Soit X Ă S. La projection de R selon X est la relation, notée πX pRq, définie par :

πX pRq “ tepXq, e P Ru.

Remarque 4.2.3
On rappelle que epXq représente les valeurs des attributs présents dans X. Par exemple, la
projection des noms des élèves ou des groupes des élèves.

Remarque 4.2.4
Le nombre d’éléments dans la nouvelle relation πX pRq est inférieur ou égale à celui de la relation
initiale R.
40 CHAPITRE 4. INITIATION AUX BASES DE DONNÉES

Exemple 4.2.5
Table des attributs nom et prénom des élèves : πnom,prénom pElèveq.

Définition 4.2.6
[Sélection] Soit A P S et a P dompAq. On appelle sélection de R selon A “ a la relation, notée
σA“a pRq, définie par :
σA“a pRq “ te P R, e.A “ au.

Remarque 4.2.7
Lorsque les domaines des attributs le permettent, le critère de sélection peut utiliser d’autres
relations de comparaison et aussi des opérations (ď, ě, ă, ą, somme, produit . . . ). La sélection
peut aussi être effectuée selon plusieurs attributs.

Exemple 4.2.8
Table des notes dont la valeur est 20 : σvaleur“20 pN otesq.

Exemple 4.2.9
Table des notes inférieures à 10 de la semaine 1 : σvaleură10,semaine“1 pN otesq.

Exemple 4.2.10
Table des identifiants des élèves qui ont eu la note 20 au moins une fois : πid pσV aleur“20 pN otesqq.

Proposition 4.2.11
La sélection et la projection sont des opérateurs commutatifs.

Exercice 4.4. On considère les tables « Elèves » et « Notes ». À l’aide des opérateurs relationnels,
exprimer les requêtes suivantes :
1. Table des élèves dont le nom est Maz.
2. La table des noms et prénoms des élèves du groupe 1.
3. La table des notes de l’élève Lamp Steevy dont l’identifiant est 3.
4. La table des identifiants des élèves qui ont eu une note inférieure à 10.

4.2.2 Produit cartésien et jointure

Définition 4.2.12
[Produit cartésien]
Soient RpSq et R1 pS 1 q deux relations de schémas S et S 1 disjoints. Le produit cartésien de R et
R1 est la relation notée R ˆ R1 définie par :

R ˆ R1 “ tpe1 , . . . , en , e11 , . . . , e1m q{pe1 , . . . , en q P R et pe11 , . . . , e1m q P R1 u.

Le schéma relationnelle de R ˆ R1 est S Y S 1 .


4.3. REQUÊTES SQL 41

Remarque 4.2.13
Si les schémas des relations ne sont pas disjoints, on peut effectuer un renommage avant le produit
cartésien. Le relation obtenue après le renommage de l’attribut A1 en B1 dans la relation R est
notée σA1 ÐB1 pRq.

(a) E1 (b) E2 (c) E1 ˆ E2


valeur nom id id nom prénom valeur nom id id nom prénom
15 Vas 1 1 Maz Max 15 Vas 1 1 Maz Max
12 Beg 3 3 Lamp Steevy 15 Vas 1 3 Lamp Steevy
12 Beg 3 1 Maz Max
12 Beg 3 3 Lamp Steevy

Table 4.3 – Produit cartésien

Définition 4.2.14
[Jointure] Soient RpSq et R1 pS 1 q deux relations de schémas S et S 1 disjoints. On considère A P S
et A1 P S 1 tels que dompAq “ dompA1 q. La jointure symétrique de R et R1 selon A “ A1 est la
relation, notée R ’ R1 , définie par :
A“A1

R ’ R1 “ σA“A1 pR ˆ R1 q.
A“A1

(c) R1 ’ R2
(a) R1 (b) R2 R1.id“R2.id
valeur nom id id nom prénom valeur nom id id nom prénom
15 Vas 1 1 Maz Max 15 Vas 1 1 Maz Max
12 Beg 3 3 Lamp Steevy 12 Beg 3 3 Lamp Steevy

Table 4.4 – Jointure

Exercice 4.5. On considère les tables « Elèves » et « Notes ». À l’aide des opérateurs relationnels,
exprimer les requêtes suivantes :
1. La table des noms, prénoms et notes.
2. Table des noms, prénoms, notes et matières.
3. La table des notes du groupe 2 de la semaine 1.
4. La table des noms, prénoms et identifiants des élèves dont une note est inférieure à 10 entre la
semaine 1 et la semaine 15.
5. La table des élèves qui n’ont pas de note entre les semaines 10 et 15.
6. La table des élèves dont toutes les notes sont inférieures à 8 entre les semaines 10 et 15.

4.3 Requêtes SQL


Les requêtes permettant d’interroger une base de données ont la structure suivante :

SELECT . . . F ROM . . . W HERE . . .

SELECT : cette clause correspond à l’opérateur de sélection et permet de déclarer une liste d’attributs.
FROM : déclare la liste des tables nécessaire à la requête.
42 CHAPITRE 4. INITIATION AUX BASES DE DONNÉES

WHERE : c’est la clause permettant de définir les prédicats en utilisant la logique propositionnelle.
JOIN ...ON : jointure de deux tables, le critère de jointure est introduit par ON.
NOT IN : réalise la différence de deux tables.
UNION : réunion de deux tables ayant les mêmes attributs.
INTERSECT : intersection de deux tables ayant les mêmes attributs.
ORDER BY : Trie la table selon l’attributs en argument.
LIMIT 0, 30 : limite le nombre de ligne affichées à la fois à l’écran.
1. Projection : liste des identifiants, noms et prénoms des élèves.
SELECT id , nom , prénom
FROM Elèves
L’opérateur ˚ permet d’afficher toute la table.
SELECT ∗
FROM Elèves
2. Sélection : liste des lignes de la table Note pour lesquelles la note est 20.
SELECT ∗
FROM Notes
WHERE valeur =20
La table Notes possède la clé étrangère « élève ». Pour ne sélectionner qu’une note de valeur 20
par élève, on utilise la clause DISTINCT.
SELECT DISTINCT ∗
FROM Elèves
WHERE valeur =20
3. Liste des noms et prénoms des élèves qui ont eu au moins une note égale à 20. Il y a deux façons
de réaliser une jointure sur deux tables.
SELECT DISTINCT Elèves .nom , Elèves .prénom
FROM Elèves , Notes
WHERE Elèves .id = Notes .id AND Notes . valeur =20
SELECT DISTINCT Elèves .nom , Elèves .prénom
FROM Elèves JOIN Notes ON Elèves .id=Notes .id
WHERE Notes .valeur =20
4. Les noms et prénoms des élèves qui n’ont jamais eu moins de 10. On commence par extraire la
table des élèves qui ont déjà eu une note inférieure à 10.
SELECT E.nom , E. prénom
FROM Elèves AS E
JOIN Notes AS N ON E.id=N.id
WHERE N.valeur <10
La requête finale :
SELECT E.nom , E. prénom
FROM Elèves AS E
WHERE (E.nom , E. prénom )
NOT IN (
SELECT E.nom , E.prénom
FROM E
JOIN Notes AS N ON E.id=N.id
WHERE N.valeur <10
)
4.3. REQUÊTES SQL 43

5. Les élèves qui ont eu 20 la semaine 1 ou la semaine 2.


SELECT E.id , E.nom , E.prénom , E.groupe
FROM Elève As E
JOIN Notes As N ON E.id=N.id
WHERE N.valeur =20 AND N. semaine =1

UNION

SELECT E.id , E.nom , E.prénom , E.groupe


FROM Elève AS E
JOIN Notes AS N ON E.id=N.id
WHERE N.valeur =20 AND N. semaine =2

Exercice 4.6. Reprendre les questions des exercices 4.4 et 4.5 et traduire les formules de l’algèbre
relationnelle obtenues dans le language SQL.

4.3.1 Requêtes d’agrégation


Les requêtes d’agrégations permettent de trier ou d’exploiter les données d’une recherche :
GROUP ...BY : effectuer une partition sur résultat d’un requête.
ORDER ...BY : Trier les résultats, avec l’option ASC (pour croissant) ou DESC (pour décroissant).
HAVING ( ) : introduire une condition sur la fonction d’agrégation. Cette clause prend la place du
WHERE après GROUP BY.
Une fois regroupé ou trié, on peut appliquer les fonctions d’agrégations suivantes :
COUNT ( ) : calculer les effectifs de chaque sous-ensemble de la partition.
MAX ( ) et MIN ( ) : maximum et minimum de l’attribut en argument pour chaque sous-ensemble
de la partition.
SUM ( ) et AVG ( ) : somme et moyenne de l’attribut en argument pour chaque sous-ensemble de la
partition.
Quelques exemples d’utilisations :
1. Nombre total de notes :
SELECT COUNT ( ∗ )
FROM Notes

2. Nombre total de notes et moyenne de la classe :


SELECT COUNT ( ∗ ) , AVG(valeur )
FROM Notes

3. Les valeurs des notes et leur nombre d’occurrences :


SELECT valeur , COUNT (valeur )
FROM Notes
GROUP BY valeur

4. Nom, prénom et moyenne des élèves :


SELECT nom , prénom , AVG( valeur )
FROM Elève JOIN Notes ON Elève .id=Notes .id
GROUP BY Notes .id

5. Joindre les tables Elèves, Notes et Colleurs :


44 CHAPITRE 4. INITIATION AUX BASES DE DONNÉES

SELECT ∗
FROM ( Elève JOIN Notes ON Elève .id=Notes .id )
JOIN Colleurs ON Notes .nom=Colleur.nom
6. Donner les nom, prénom et moyenne des élèves par colleur :
SELECT E.nom , E.prénom , C.nom , AVG(valeur )
FROM ( Elève AS E JOIN Notes AS N ON E.id=N.id )
JOIN Colleurs AS C ON N.nom=C.nom
GROUP BY E.id , C.nom
Attention ! il est indispensable de préciser de quelle table sont issus les attributs nom et prénom.
7. Nom, prénom et moyenne des élèves ayant une moyenne supérieure ou égale à 15 :
SELECT E.nom , prénom , AVG(Valeur )
FROM Elève AS E
JOIN Notes ON E.id=Notes .id
GROUP BY E.id
HAVING AVG(Notes .valeur )>= 15

Exercice 4.7. Donner la table des groupes de colle et la moyenne de chaque groupe.

Exercice 4.8. Nom et prénom des élèves dans l’ordre des moyennes décroissantes.
Bases de données : TP 1
Pour commencer le TD :
— Ouvrir le logiciel SQLiteSpy.
— Ouvrir, avec SQLiteSpy, la base de donnée « Videoclub » ce trouvant au même emplacement
que le logiciel.
Le Schéma relationnel de la base de donnée « Videoclub »est le suivant :
— Personne (idPersonne, nom).
— Realisateur (7 idPersonne, 7 idFilm).
— Acteur (7 idPersonne, 7 idFilm).
— Film (idFilm, titre_VO, titre_VF, année, pays).
— Client (numClient, nom, ville, credit, bonus).
— Emprunte (numClient, 7 numInventaire, dateEmprunt).
— Exemplaire (numInventaire, 7 idFilm, format).

Exercice 4.3.1
Dans la base de donnée « Videoclub » (sans réaliser de requêtes SQL) :
1. Chercher l’identifiant de « Alan Napier ».
2. Vérifier que la personne »Heath Ledger » n’est pas dans la base de donnée.
3. On souhaite ajouter le film L’Associé du diable, The Devil’s Advocate datant de 1998, réalisé
au USA par Taylor Hackford avec Al Pacino, Keanu Reeves, Charlize Theron.
(a) Ajouter, dans la table « Film », le film L’Associé du diable, The Devil’s Advocate,
1998, USA.
(b) Ajouter le réalisateur Taylor Hackford.
(c) Ajouter les acteurs Al Pacino, Keanu Reeves et Charlize Theron.
4. Ajouter le film suivant : The Dark Knight, Le chevalier noir, The Dark Knight, 2008, USA
réalisé par Christopher Nolan avec Christian Bale, Heath Ledger, Aaron Eckhart.

Exercice 4.3.2
Exécuter les requêtes suivantes après les avoir formulées à l’aide des opérateurs de l’algèbre
relationnelle.
1. Donner les films plus récents que 2008.
2. Donner la liste des clients dont la ville est Gif-sur-Yvette et dont le bonus est entre 0 et 1.
3. Donner les identifiants des personnes à la fois acteurs et réalisateurs.
4. Quels sont les films où joue « Belmondo ».
5. Quels sont les réalisateurs de « Gran Torino ».
6. Quels sont les films où « Clint Hiswood » est à la fois acteur et réalisateur.
7. Quels sont les films où joue « » et « » ?
8. Donner le nombre de films par nationalité.
9. Donner la liste des villes par ordre croissant possédant le plus de clients.
Bases de données : TP 2
Correction des exercices
Bibliographie

[1] Cormen T. Introduction to algorithm.


[2] Casamayou-Boucau A. Programmation en Python pour les mathématiques, Dunod (2013).
[3] Swinnen G. Apprendre à programmer avec Python3.
[4] Wack B. Informatique pour tous en CPGE.

49

Vous aimerez peut-être aussi