Vous êtes sur la page 1sur 99

République Tunisienne

‫الجمهوريـــة التونسيـــة‬
Ministère de l’Enseignement Supérieur, de la Recherche
‫وزارة التعلين العالي و البحث العلمي‬
Scientifique

UNIVERSITE DE GABES
Institut Supérieur des Sciences Appliquées et de ‫جامعة قابس‬
Technologie de Gabès ‫المعهد العالي للعلىم التطبيقيت والتكنىلىجيا بقابس‬

Auditoire : 1ère Année cycle préparatoire aux études d’ingénieurs

Enseignants : Fayçal Arrami, Jamel Bahri, Awatef Benfradj, Souhir Bouaziz,


Fatma Meftah, Zied Lakhal

Année universitaire : 2016/2017


ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

CHAPITRE I:
Rappel des notions algorithmiques

1. Introduction
Un algorithme est une suite d'opérations que devra effectuer pour arriver en un temps fini, à un
résultat désiré à partir d'une situation donnée. Cette suite sera formée d'actions élémentaires
appelées instructions.
Pour développer un algorithme résolvant un problème donné, deux approches sont possibles :
l’approche descendante et l’approche ascendante.
Dans ce cours nous nous intéresserons à l'approche descendante vue que l’approche descendante est
systématique et permet d’arriver rapidement à un squelette d’algorithme.
L’approche descendante consiste à décomposer le problème initial en sous problèmes de plus petite
taille et ainsi de suite jusqu’à arriver à des problèmes solubles.

2. Les étapes de résolution d’un problème


Le cycle de vie de la résolution d’un problème est le suivant :
 Comprendre l'énoncé du problème
 Décomposer le problème en sous-problèmes plus simple à résoudre
 Associer à chaque sous problème, une spécification :
 Les données nécessaires
 Les résultats attendus
 La démarche à suivre pour arriver au résultat en partant d'un jeu de données.
 Elaboration d'un algorithme.

3. Composants d’un algorithme


3.1. Les objets élémentaires (les données)
3.1.1. Les constantes :
Une constante est un objet ayant une valeur inchangée tout le long d'un algorithme.
Elle est caractériser par : Son nom (un identificateur unique) et Sa valeur.
Exemple : CONST Pi=3.14.
 Déclarations des objets: CONST Nom_constante = Valeur

3.1.2. Les variables :


Une variable est un objet pouvant prendre différentes valeurs tout le long d'un algorithme.
Elle est caractérisée par :
 Son nom : un identificateur unique et significatif
 Son type : déterminant ce qu'elle pourra accueillir
 Son contenu : représentant sa valeur pouvant être modifiée au cours de l'exécution.
 Déclarations des objets: VAR Nom_variable : type

3.2. Les types des données


3.2.1. Les types numériques
a) Le type entier :
 Domaine des valeurs: Désigne les valeurs des nombres entiers relatifs, codé sur 2 Octets
 Les opérateurs utilisés sur les entiers: +, *, -, DIV, MOD, >, <, <>, >=, <=, =.

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

b) Le type réel :
 Domaine des valeurs : Désigne les valeurs des nombres réels, codé sur 6 Octets
 Les opérateurs utilisés sur les réels : +, *, - , / , > , < , <>, >= , <=, = .

 Les fonctions arithmétiques standard:


NOM Rôle Exemple
Tronc (x) Supprimer la partie décimale de x TRUNC( 9.55)= 9
TRUNC(-0.15)= 0
Arrondi (x) Arrondi la valeur de x à la valeur entière le plus ROUND( 9.55)= 10
proche ROUND( 9.45)=9
Abs(x) Donne la valeur absolue de x ABS (-6) = 6,ABS (6) = 6
Carré(x) Donne le carré de x SQR( -2) = 4
Sin (x) Donne le sinus et le cosinus de x (x en radian) Sin(PI/2) = 1
Cos(x) Cos (PI/2) = 0
RacineCarré (x) Donne la racine carrée de x s’il est positif. SQRT(4) = 2
Exp(x) Donne l’exponentielle de x Exp(0)=1
Ln( x) Donne le logarithme népérien de x s’il est positif LN(1) = 0 , LN( 10) = 1
Arctan(x) Donner la valeur en radians de arc tangente x. Arctan (1) = PI/4
3.2.2. Le type booléen :
 Domaine des valeurs : deux valeurs logiques VRAI et FAUX
 Opérateurs logiques sur les booléens :
Non : Négation, ET : Conjonction, OU : Disjonction, OUex : Ou exclusif
 Table de vérité de ces opérateurs :
x y Non(x) x ET y x OU y x OUex y
F F V F F F
F V V F V V
V V F V V F
V F F F V V
3.2.3. Le type caractère :
- Un caractère est formé par le caractère lui-même défini entre apostrophes.
- Une variable de type caractère contient impérativement un caractère et un seul.
- L'espace est un caractère "blanc" (" ")
 Opérateurs sur les caractères :
Les caractères sont ordonnés selon leur code ASCII, donc on peut appliquer sur ces caractères
les opérateurs relationnels : <, >, <=, >=, =, <>.
Exemple : "A" < "B" est une proposition Vrai , "z" < "a" est une proposition Faux
 Les fonctions prédéfinies sur les caractères :
c : est un caractère, n : entier compris entre 0 et 255.
Nom Rôle Exemples
Retourne le code ASCII du caractère c. le résultat est un entier Ord("A") = 65
Ord ( c ) positif. Ord ("a") = 97
Retourne le caractère dont le code ASCII est n Chr (67) vaut "C"
Chr( n )
Chr(99) vaut "c"
Retourne le caractère successeur de c s’il existe Succ("B") est "C"
Succ ( c)
Succ("6") est "7"
Retourne le caractère prédécesseur de c s’il existe Pred ("B") est "A"
Pred( c)
Pred ("2") est "1"
Majus (c) Convertit le caractère c en majuscule Majus("s") est "S"

2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

3.2.4. Le type chaîne de caractères


Une chaîne de caractères est une suite de n caractères, n étant un entier compris entre 0 et 255.
Si n = 0 alors la chaîne est vide. La valeur d’une chaîne de caractères est définie entre guillemets.
On pourra accéder en lecture et en écriture au ième caractère d'une chaîne CH en utilisant la notion
CH [i] ù 1 <= i <= Longueur de CH.
3.2.5. Les Tableaux
Un tableau est une structure de données consistant à ranger un nombre fini d'éléments ayant le même
type et selon une disposition bien déterminée.

 Déclarations des objets:


VAR Nom_tableau : tableau [dimension] de type des éléments
Exemples :
1 ère méthode
VAR T : tableau [1..100] d’entier { T : tableau à une dimension}
M : tableau [1..25,1..25] d’entier {M : tableau à deux dimensions}
TYPE nom_type = Tableau[dimension] de type des éléments
VAR Nom_var : nom_type
Exemples :
2eme méthode TYPE TAB = tableau [1..100] d’entier
MAT = tableau [1..25,1..25] d’entier
Var T : TAB
M : MAT

 Accès aux composants :


On peut accéder directement aux éléments d’un tableau en lecture ou en écriture, en utilisant les
indices (rangs) de chaque élément.
- Tableau à une dimension : T[i] tel que 1≤ i ≤ taille du tableau : T [1], T [2], ..., T [n]
- Tableau à deux dimensions: M[i,j] tel que 1≤ i ≤ nombre_ligne et 1≤ j ≤ nombre_colonne
M [1,1], M [1,2]….,M[1,n], M [2,1]...., M[2,n],……….,M[m,1]……….,M[n,m]

4. Les structures simples


4.1. Entrée ou lecture
Les entrées rassemblent toutes les opérations de lecture des données. La source de lecture est par
défaut le clavier, mais elle pourra être un disque ou toute autre source d’entrée ou d’entrée/sortie.
 syntaxe algorithmique : Lire (identificateur) : la saisie d’une valeur à partir du clavier.

4.2. Affectation
L’opération d’affectation attribue une valeur à une variable. Elle permet soit d’initialiser la variable à
une valeur donnée soit de modifier la valeur courante d’une variable par une autre valeur.
 syntaxe algorithmique : Identificateur  valeur

4.3. Sortie ou écriture


L’opération de sortie permet d’afficher la valeur d’une variable ou un message à l’utilisateur.
L’écriture se fait par défaut sur l’écran ou bien sur tout support de stockage ou sur l’imprimante.
 syntaxe algorithmique :
 L’affichage de contenu d’une variable : Ecrire (x)
 l’affichage d’un texte (commentaire ou message) : Ecrire ("message")
 L’affichage mixte (texte et variables) : Ecrire ("message", x)

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

5. Structure d’un algorithme


L’algorithme présente la structure suivante :
Algorithme <nom_algorithme>
CONST <identificateur = valeur>
TYPE <nouveau_type = tableau(index1..index2) type>
VAR <identifiacteur : type>
Début
<lecture des données>
<traitement>
<affichage de résultat>
Fin

6. Les structures de contrôles conditionnelles


Les structures de contrôle permettent à un programme de modifier son traitement en fonction d’une
condition. Selon la valeur de la condition (vrai ou faux), l’algorithme choisit quelles instructions
seront exécutées. Deux formes de structures conditionnelles existent : la forme simple et la forme
généralisée.

6.1. Forme simple


forme simple réduite forme simple complète
SI conditions ALORS SI conditions ALORS
Traitement-1
Traitement SINON
Traitement-2
FINSI FINSI

N.B : Pour la forme simple complète, si la valeur de la condition est Vrai les instructions du
Traitement-1 seront exécutées alors que si cette valeur est fausse les instructions du Traitement-2
seront exécutées.

6.2. Forme généralisée


SI condition1 ALORS
Action1
SINON SI condition 2 ALORS
Action 2
………

SINON SI condition N-1 ALORS


Actions N-1
SINON
Actions N
FINSI

6.3. Structures à choix multiples


La structure de choix permet d’exécuter un choix parmi plusieurs alternatives. Le choix de traitement
à réaliser dépend de la valeur ou les valeurs d’une variable appelée sélecteur.

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

{Init }….
Selon Sélecteur Faire
Valeur(s)1 : Traitement 1
Valeur(s)2 : Traitement 2
……...……
Valeur(s)n : Traitement n
Sinon
Traitement n+1
Fin Selon

 Le sélecteur est une variable de type scalaire discret (entier, caractère, booléen, énuméré,
intervalle).
 Plusieurs valeurs peuvent entraîner dans un même traitement. Nous pouvons alors énumérer ces
valeurs en les séparants par des virgules, avant de décrire le traitement à entreprendre comme
nous pouvons utiliser des intervalles pour le type entier caractères.
 La partie « Sinon » est facultative.

7. Les structures itératives


Une structure itérative consiste à répéter un même traitement un certain nombre de fois. Ce nombre
est soit connu à l’avance (avant d’entrée à la boucle) soit il est en fonction d’une condition.

7.1. La structure itérative Pour


 Définition :
Un résultat a une définition complète s’il est la répétition d’une suite d’instructions, un nombre fini
de fois connu à l’avance.
 Syntaxe :
La structure itérative Pour simple La structure itérative Pour avec pas
{init} {init}
Pour compteur de vi à vf faire Pour compteur de vi à vf pas p faire
Instruction 1 Instruction 1
Instruction 2 Instruction 2
…….. ……..
Instruction n Instruction n
FinPour FinPour

 Remarque :
 vi : valeur initiale du compteur
 vf : valeur finale du compteur
 Le compteur est une variable de type scalaire (Entier, caractère ou booléen).
 Le traitement de la boucle « Pour » s’arrête lorsque le compteur atteint la valeur finale (vf).
 Dans la boucle « Pour simple », à chaque répétition, le compteur sera automatiquement
incrémenté (augmenté) d’une unité (compteur compteur +1)
Dans la boucle « Pour avec pas », à chaque répétition, le compteur sera automatiquement :
- incrémenté (augmenté) d’une pas=p ( compteur compteur +p si vi < vf )
- décrémenté (retranché) d’une pas=p ( compteur compteur -p si vi > vf )

5
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 Quelques traitements de base sur les tableaux :


La structure pour se prête particulièrement bien au travail avec les tableaux (Saisie,
Affichage, …)

Saisie Affichage

Pour i de 1 à N faire Pour i de 1 à N faire


tableau à une Ecrire(« donner l’élément n : »,i) Ecrire (T[i])
dimension Lire(T[i]) Fin pour
Fin pour

Pour i de 1 à L faire Pour i de 1 à L faire


Pour j de 1 à C faire Pour j de 1 à C faire
tableau à deux
Lire(M[i,j]) Ecrire (M[i,j])
dimensions
Fin pour Fin pour
Fin pour Fin pour

7.2. Les structures itératives à condition d’arrêt


7.2.1. Première formulation : répéter…jusqu'à :
 Définition :
Un résultat a une définition itérative à condition d’arrêt s’il est la répétition d’une suite d’instructions
jusqu'à ce que la condition passe à l’état vrai. La répétition est contrôlée par un prédicat (condition)
qui exprime la condition d’arrêt de la boucle (le nombre de répétitions est inconnu d’avance).
 Syntaxe :
Au niveau de l’algorithme
{init}
Répéter
Instruction 1
Instruction 2
……..
Instruction n
Jusqu'à condition d’arrêt

 Remarque :
 Cet ordre d’itération permet de répéter le traitement un ou plusieurs fois.
 En effet lorsque la condition est vérifiée la boucle s’arrête, sinon elle ré-exécute le traitement.
 Il doit y avoir une action dans le traitement qui modifie la valeur de la condition.
 La structure itérative à condition d’arrêt répéter jusqu'à peut remplacer la structure itérative
complète. Mais le contraire n’est pas valable.

7.2.2. Deuxième formulation : Tant que…faire…


 Définition :
Cette instruction permet de répéter le traitement 0 ou plusieurs fois elle est contrôlée par un prédicat
qu’exprime la condition d’arrêt. Ce prédicat est évalué avant chaque exécution de la boucle, s’il est à
l’état faux la boucle s’arrête. Le nombre de répétitions est inconnu d’avance.

6
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 Syntaxe :
Au niveau de l’algorithme
{init}
Tant que (non arrêt) faire
Instruction 1
Instruction 2
……..
Instruction n
Fin Tant que
 Remarque :
 Le paramètre de la condition doit être initialisé par lecture ou par affectation avant la boucle,
car si l’initialisation n’a pas été faite, le traitement itératif risque de ne pas être exécuté.
 Il doit y avoir une action dans le traitement qui modifie la valeur de la condition.
 Contrairement au Répéter jusqu’à, on remarque que la condition est d’abord testée, puis si elle
est satisfaite, l’action est exécutée (la condition précède toujours l’action).
 RETENONS :
Pour les structures itératives à condition d’arrêt, le traitement de la boucle « REPETER » s’exécute
dans tous les cas au moins une fois alors que pour la boucle « TANT QUE », on peut tomber dans un
cas où le traitement correspondant ne s’exécute pas aucune fois et ceci si dès la première évaluation
la condition est fausse.

Bibliographie :
1. http://4bts.blogspot.com/p/algorithme_1021.html
2. https://fr.scribd.com/document/89884054/Cours-Algorithme
3. https://sites.google.com/site/mahdhaouibrahim/resolutions
4. http://www.kiteb.net/education/informatique/programmation/scientifiques/fiches/fiche-
scalaire-intervalle-tableau.pdf
5. http://xn--webducation-dbb.com/?media_dl=1555

7
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

CHAPITRE II:

Environnement de développement python 3

1. Introduction
Python est développé depuis 1989 par Guido van Rossum et de nombreux contributeurs. Un
classement des langages de programmation les plus populaires, par
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Classement de TIOBE
Avril 2017 Avril 2016 Langage de programmation Evaluation Changement
1 1 Java 15.568% -5.28%
2 2 C 6.966% -6.94%
3 3 C++ 4.554% -1.36%
4 4 C# 3.579% -0.22%
5 5 Python 3.457% +0.13%
6 6 PHP 3.376% +0.38%
7 10 Visual Basic .NET 3.251% +0.98%
8 7 JavaScript 2.851% +0.28%
9 11 Delphi/Object Pascal 2.816% +0.60%
10 8 Perl 2.413% -0.11%
11 9 Ruby 2.310% -0.04%
12 15 Swift 2.287% +0.81%

Python est un langage puissant, à la fois facile à apprendre et riche en possibilités. De


nombreuses fonctionnalités intégrées seront disponible, dès son installation.
Il est, en outre, très facile d'étendre les fonctionnalités existantes. Ainsi, il existe ce qu'on
appelle des « bibliothèques » qui peuvent ainsi être installées pour aider le développeur à
travailler sur des projets particuliers.
Concrètement, voilà ce qu'on peut faire avec Python :
 de petits programmes très simples, appelés scripts;
 des programmes complets, comme des suites bureautiques, des jeux, des clients de
messagerie, des logiciels multimédias …
 des projets très complexes, comme des progiciels « ensemble de plusieurs logiciels
pouvant fonctionner ensemble, principalement utilisés dans le monde professionnel ».
Python est un langage de programmation interprété, c'est-à-dire que les instructions que
vous lui envoyez sont transcrites en langage machine au fur et à mesure de leur lecture.
D'autres langages (comme le C ou C++) sont appelés langages compilés car, avant de
pouvoir les exécuter, un logiciel spécialisé se charge de transformer le code du programme
en langage machine. On appelle cette étape la compilation. À chaque modification du
code, il faut rappeler une étape de compilation.
Un langage interprété a comme avantages : sa simplicité (pas d’étape de compilation avant
l'exécution) et la portabilité (fonctionne quel que soit le système d’exploitation sans
changement dans le code). Cela ne veut pas dire que les langages compilés ne sont pas

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

portables, mais on doit utiliser des compilateurs différents et, d'un système à l'autre,
certaines instructions ne sont pas compatibles, voire se comportent différemment.

2. Premiers pas avec Python


2.1. L’application Idle
L’application Idle (Integrated DeveLopment Environment) permet à la fois :
- d’utiliser Python en mode interactif (entrer des commandes, recevoir une
réponse, recommencer …)
- d’écrire et sauvegarder des programmes (on dit aussi des scripts ou mieux
des modules) puis de les exécuter.
2.2. Premiers essais avec Idle en mode calculatrice
À l’invite du « prompt » de l’application Idle, on peut commencer par entrer et évaluer des
expressions très simples (en général sur une seule ligne) avec retour au prompt après
évaluation. Tout ce qui suit le caractère # est considéré comme un commentaire. Il est
possible de se référer au résultat du calcul précédent avec le caractère de soulignement _.

Il est possible d’entrer une expression longue de plus d’une ligne (ou de forcer des passages à
la ligne ne devant pas être interprétés comme des demandes d’évaluation) avec le caractère \.

2.3. Variables : initialisation avant utilisation


Pour mémoriser des valeurs, on les associe (on les lie, on les affecte, on les assigne) à
des identificateurs. Le couple identificateur/valeur est appelé une variable.

2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Python n’est pas un outil de calcul formel. Il faut donc toujours initialiser une variable
avant de l’utiliser :

Une même variable (en fait un même identificateur) peut être successivement lié à des
valeurs de types différents (entiers, chaînes de caractère, etc.). Il n’y a donc pas lieu de
préciser au préalable le type de valeur que l’on désire placer dans telle ou telle variable (tout
cela est réalisé au moment de l’évaluation : c’est ce qu’on appelle le typage dynamique).

2.4. Variables : affectations simultanées


Il est possible d’effectuer simultanément plusieurs affectations de variables (de même type
ou non).

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

2.5. Noms de variables et mots réservés


Comme nom de variable, on peut utiliser tous les identificateurs de son choix, à l’exception
de quelques mots qui sont strictement réservés par le langage, et donc voici la liste :

2.6. Quelques fonctions intégrées


Au lancement de l’application Idle (donc de l’interpréteur Python), un certain nombre de
fonctions sont automatiquement chargées en mémoire (finalement pas si nombreuses : les
fonctions plus spécialisées sont accessibles en important explicitement des modules.

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

2.7. La fenêtre d’édition dans l’application Idle


Dès qu’on commence à écrire des programmes de quelques lignes, on ne peut se contenter
du mode interactif de l’application Idle (le “Python Shell”).
Pour sauvegarder son travail, le modifier, l’utiliser (le “lancer”), on utilise la fenêtre
d’édition de l’application Idle. Voici comment tout cela peut se passer :
 on ouvre une nouvelle fenêtre d’édition (File/New Window)
 on y écrit une succession de définitions et d’instructions, dans l’ordre où on pourrait
les entrer en mode interactif
 on sauvegarde le document avec l’extension .py (sans être obligatoire, cette extension
est recommandée)
 on peut tester la syntaxe du module (Run/Check Module)
 on lance l’exécution du module (Run/Run Module), ce qui ramène dans la fenêtre du
mode interactif (Python Shell)
 à tout moment, on peut revenir dans la fenêtre d’édition, modifier le module, le lancer
à nouveau.

3. Types élémentaires classes int, str, float, bool, complex)


3.1. Types simples
Python propose 4 types simples de base. Ils sont dits simples (ou scalaires, atomiques) car
ils permettent de stocker une seule donnée par variable. Il s'agit de :
 bool : booléen (état vrai ou faux)
 int : entier
 float : réel flottant
 complex : complexe flottant

Voici les principales opérations sur les types numériques :

5
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Il est courant d’avoir à incrémenter une variable. L’instruction i = i+1 sera avantageusement
remplacée par i += 1. On dit que += est un opérateur avec assignation.
Voici la liste des opérateurs avec assignation de Python. Leur portée va bien au delà des types
numériques : ils s’appliquent à tous les types sur lesquels l’opération (addition, produit, etc.) a
un sens.

3.2. Les fonctions mathématiques du module math


La plupart des fonctions mathématiques usuelles (racine carrée, sinus, logarithme, etc.)
ne sont pas chargées en mémoire au démarrage de l’interpréteur Python. Elles appartiennent
à un module nommé math qu’il faut donc importer. Il y a plusieurs possibilités
(l’instruction choisie doit bien sûr précéder l’utilisation des fonctions intégrées au module) :

Quand le module math a été chargé, on obtient le détail des fonctions qu’il contient en tapant
help(math). Voici l’essentiel des fonctions du module math, évaluées en un argument x
quelconque :

6
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

3.3. Egalité structurelle et égalité physique


Quand on affecte une valeur à une variable (par exemple x = 2013), on crée en fait
un pointeur (une adresse) pour désigner cette valeur qu’il faut imaginer quelque part en
mémoire. Les variables Python sont donc des références (des adresses, des pointeurs) vers
des valeurs. Pour connaître l’adresse où se trouve exactement la valeur qu’on a
associée à un identificateur, on utilise la fonction intégrée id.
L’égalité structurelle de deux objets signifie l’égalité de leurs valeurs, alors que l’égalité
physique signifie l’égalité des adresses de ces valeurs (bien sûr l’égalité physique implique
l’égalité structurelle, mais la réciproque est fausse). Pour tester l’égalité structurelle, on
utilise l’opérateur ==, et pour l’égalité physique, on utilise l’opérateur is.
Ces distinctions ne sont pas très importantes quand on manipule des objets dits “non
mutables” (comme les types de base : entiers, flottants, nombres complexes, chaînes
de caractères, et également les tuples qui seront étudiés plus tard). En revanche, la
distinction entre égalité physique et égalité structurelle prend tout son sens quand on
modifie les éléments d’objets “mutables” (comme les listes ou les dictionnaires).

7
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

On va maintenant effectuer des opérations analogues, mais sur des listes :

On continue sur cet exemple, en redéfinissant la liste y

On va maintenant recopier à nouveau x dans y, mais modifier seulement un élément de y.

L’exemple précédent est important. Les listes Python sont des objets composites (formés
d’éléments a priori disparates mais rassemblés dans une même structure). Si on modifie un
élément d’une liste, Python ne modifie pas l’adresse de celle-ci (en fait, il modifie
seulement l’adresse de l’élément concerné dans cette liste). Cela explique qu’après
l’instruction y = x (à l’issue de laquelle x et y pointent sur une même liste en mémoire), la
modification y[0] = 999 semble répercutée sur la liste contenue dans la variable x (tout
simplement car les variables x et y continuent à pointer sur la même adresse). L’instruction
y = x n’a donc pas associé à y une nouvelle copie de la liste associée à x, elle a fait pointer
y et x sur une même adresse (toute modification d’un des deux éléments x[k] ou y[k] sera
donc “répercutée” sur l’autre). Si on veut créer une copie d’une liste qui soit indépendante
de l’original, on procédera de la façon suivante :

8
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Remarque : l’expression x[:] est un cas particulier de la syntaxe x[a:b] qui renvoie la liste
des éléments de l’objet x situés de la position a (incluse) à la position b (exclue). Par défaut a
vaut 0 (c’est le début de l’objet x) et b vaut la longueur de cet objet. Ainsi x[:] envoie
donc la totalité de l’objet x (mais cette copie est indépendante de l’original).

4. Programmation Python
4.1. Entrée au clavier (input) et affichage à l’écran (print)
Les interactions d’un script avec l’utilisateur se feront essentiellement par l’attente de
données entrées au clavier, et par l’affichage de résultats ou de messages à l’écran.
L’expression input(message) affiche message à l’écran (sans passer à la ligne), attend que
l’utilisateur valide par “Entrée” une réponse au clavier, et renvoie cette réponse sous forme
de chaîne de caractères.

On peut bien sûr directement convertir la réponse reçue par input en un type particulier (int
et float notamment) :

La fonction print permet d’afficher des informations à l’écran. Il s’agit le plus souvent de
messages informatifs qui peuvent intervenir à tout moment de l’exécution du script.
Il est possible d’afficher successivement plusieurs objets sur une même ligne (ils sont alors
séparés par un espace, mais on peut préciser un autre séparateur avec l’option sep=). Un
affichage par print se termine par un passage à la ligne (mais on peut préciser un autre mode
de terminaison avec l’option end=)

9
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

4.2. Structure de contrôle conditionnelle if


La clause if simple permet d’exécuter un bloc d’instructions si la condition est vraie :

Exemple :
Ecrire un programme qui saisi un nombre et teste si l’entier est nul, pair ou impair.

10
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Application
Ecrire un programme qui saisi trois entiers a, b et c et résout l’équation de second degré
ax2+bx+c= 0.

4.3. Les structures itératives conditionnelles : Boucle while


Pour répéter un bloc d’instructions tant qu’une condition est réalisée, Python nous propose
la clause while :

Le bloc qui fait suite à l’instruction while peut contenir deux instructions
particulières, souvent attachées à un test if :
 break provoque la sortie immédiate de la clause while.
 continue ramène à l’évaluation de la condition (ce qui restait du bloc après
continue est donc ignoré).
Exemple :
On appelle suite de Syracuse une suite d’entiers naturels définie de la manière suivante :
On part d’un nombre entier plus grand que zéro; s’il est pair, on le divise par 2 ; s’il
est impair, on le multiplie par 3 et on ajoute 1. En répétant l’opération, ….

11
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Exercice 1 : Jeu de devinette


Ecrire un programme devinette qui permet de deviner un entier généré par le programme de
façon aléatoire (compris entre 1 et 100), on indiquera à l’utilisateur si l’entier introduit est
plus grand ou plus petit que l’entier caché.
Un bravo sera affiché lorsqu’il aurait deviné l’entier, on lui indiquera également au bout
de combien de tentatives il est parvenu à trouver le nombre.
Rq: pour générer un entier aléatoire il faut importer le package random, puis utiliser la
fonction randint(a,b) où a et b désigne l’intervalle [a,b] dans lequel l’entier aléatoire sera
tiré.

Exercice 2 :
Modifier le programme précédant en ajoutant 3 niveaux de difficulté (difficile (4 tentatives),
Moyen (7 tentatives) ou facile (12 tentatives)).
Le joueur choisi un niveau de difficulté, un nombre d’essai lui est alors attribué, si ce dernier
épuise ses essais il aurait échoué et un message sera affiché.
Remarque: On lui indiquera à chaque fois le nombre de tentatives restantes.

12
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

4.4. Les structures itératives Les non conditionnelles : Boucle for


L’intervalle range(a,b,h) doit être vu comme une succession de valeurs, en partant de a, et en
progressant vers b (sans jamais l’atteindre !), dans le sens croissant ou décroissant selon
que le pas est positif ou négatif.
- la valeur a (le début de l’intervalle) est facultative, et par défaut elle vaut 0.
- la valeur h (le pas de l’intervalle) est facultative, et vaut 1 par défaut.

Exemple :
- l’intervalle range(7) représente la succession des valeurs 0, 1, 2,3, 4, 5, 6
- l’intervalle range(1,7) représente la succession des valeurs 1, 2, 3, 4, 5, 6
- l’intervalle range(1,7,2) représente la succession des valeurs 1, 3, 5
- l’intervalle range(7,2) est vide (ici le pas a sa valeur par défaut, c’est-à-dire 1)
- l’intervalle range(7,2,-1) représente la succession des valeurs 7, 6, 5, 4, 3

Pour répéter un certain nombre de fois un bloc d’instructions, on utilisera la construction


suivante.

13
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Application
Écrire un programme python qui affiche tous les nombres cubiques formés de trois digits
exemples 153 = 13 + 53 + 33

5. Les séquences (chaînes, tuples, listes)


5.1. Propriétés communes aux séquences (hors “mutations”)
Il n’y a pas à proprement parler de type séquence en Python, mais on désigne comme tels les
objets qui appartiennent à l’un des trois types suivants : les chaînes de caractères, les listes, et
les tuples.
Au-delà des différences entre ces types de données, les séquences ont un certain nombre de
propriétés importantes en commun :
- elles sont composées d’un nombre fini d’éléments auxquels on peut accéder par un
indice. Ainsi seq[k] désigne l’élément situé en position k dans la séquence seq (la
numérotation commence à 0).
- un indice négatif signifie qu’on compte à partir de la fin. Ainsi seq[-1] désigne le
dernier élément d’une séquence.
- on peut effectuer des coupes (le terme anglais est slice). Ainsi seq[i:j] désigne la
séquence (chaîne, liste ou tuple) formée des éléments qui sont en position i (inclus) à j
(exclu) dans la séquence seq
- on peut tester l’appartenance d’un élément à une séquence. La syntaxe est elt in seq
(résultat booléen)
- on peut parcourir une séquence au sein d’une boucle for. La syntaxe est for elt in seq
- la longueur d’une séquence seq (le nombre d’éléments dont elle est constituée) est
donnée par len(seq)
Dans le tableau ci-dessous, s et t désignent des séquences (chaînes, listes ou tuples), x désigne
un objet pouvant appartenir à s, et on note i, j, k, n des entiers :

14
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

 Les chaînes de caractères sont délimitées par des guillemets doubles ("abc") ou
simples ('abc').
 Les listes sont des successions d’objets (eux-mêmes séparés par des virgules),
délimitées par des crochets [ et ]. Elles peuvent contenir des objets de type
quelconque. Un exemple de liste est [1,'a',[3.14,'xyz']].
 Les tuples sont des successions d’objets (séparés par des virgules), délimitées par des
parenthèses ( et ). Les tuples peuvent contenir des objets de type quelconque. Un
exemple de tuple est : (1,'a',[3.14,'xyz']).

Remarquons que les fonctions intégrées list, tuple et str permettent de passer d’un type de
séquence à l’autre :

5.2. Séquences mutables ou non


Rappelons que quand on crée une variable, donc lorsqu’on lie un identificateur à un objet par
l’instruction nom=obj, on associe en fait à cet identificateur l’adresse en mémoire où se
trouve physiquement l’objet. On exprime cette situation en disant qu’on crée une référence,
ou encore un pointeur, vers l’objet. Il y a une différence importante entre les listes d’une part,
et les chaînes et tuples de l’autre : les listes sont dites mutables, mais les chaînes et les tuples
ne le sont pas.
Dire qu’un objet est mutable, c’est dire qu’on peut en modifier (voire en supprimer) un (ou
plusieurs) élément(s), sans pour autant créer une nouvelle référence vers l’objet ainsi modifié
(l’adresse du début de l’objet reste inchangée).

15
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Par exemple, si on pose x = y = [5, 2, 9], on définit deux variables x et y contenant en fait
l’adresse d’une unique liste. On peut poser x[0] = 10 : on mute donc la liste dont le contenu
est maintenant [10, 2, 9], mais dont l’adresse ne change pas en mémoire. Les variables x et y
pointent donc toujours vers la même adresse, à laquelle on trouve la liste [10,2,9].

5.3. Les listes


Les listes peuvent être formées :
- en évaluant l’expression list() ou []. On obtient la liste vide.
- en combinant des éléments [elt0, elt1,..., eltn], ou en convertissant une séquence par
list(seq).
- en “compréhension”, par [expr for indice in iterable], ou [expr for indice in iterable
if condition].
Exemples :

16
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Quelques manipulations supplémentaires sur une liste L :

17
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

5.4. Les tuples


Les tuples sont des séquences non mutables d’objets séparés par une virgule, et délimitées par
des parenthèses ( et ).
Les tuples peuvent être formés :
- en évaluant l’expression tuple() ou (). On obtient le tuple vide.
- en combinant des éléments (elt0, elt1,..., eltn), ou en convertissant une séquence par
tuple(seq).
- en “compréhension”, par tuple(expr for indice in iterable), ou (expr for indice in
iterable if condition) ;
Les opérations sur les séquences non mutables s’appliquent aux tuples : appartenance (avec in
t et not in t), concaténation (avec t + t’) et répétition (avec t * n), longueur avec len(t), accès
indexés et coupes (avec t [ i ], t [ i : j ], t [ i : j : k ]), minimum/maximum (max et min),
recherche de valeur x par index.t(x) et occurrences par t.count(x).

5.5. Les chaînes de caractères


Les chaînes sont des séquences de caractères non mutables. On ne peut donc pas modifier un
ou plusieurs caractères. Si on ajoute un caractère (ou une autre chaîne) par concaténation à
une chaîne existante, le résultat est la création d’une nouvelle chaîne à une nouvelle adresse
en mémoire. Les chaînes sont délimitées par des guillemets simples ('bonjour'), doubles
("bonjour") ou triples ('''bonjour'''). La possibilité de choisir entre les délimiteurs simples ou
doubles permet d’insérer des guillemets dans une chaîne (on pourra par exemple former la
chaîne "c'est l'automne").
Les opérations sur les séquences non mutables s’appliquent aux chaînes :
- appartenance (avec in ch et not in ch),
- concaténation (avec ch + ch') et répétition (avec ch * n),
- longueur avec len(ch), accès indexé et coupes (avec ch [ i ], ch [ i : j ], ch [ i : j : k ])
- minimum/maximum (max et min)
- recherche de x par ch.index(x) et occurences par ch.count(x).

18
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Tout comme les listes et les tuples, les chaînes sont itérables, et peuvent donc être parcourues
dans une boucle for. Voici quelques exemples d’opérations possibles sur les chaînes de
caractères :

Les chaînes possèdent un très grand nombre de méthodes qui leur sont propres ; ces méthodes
ont souvent un comportement par défaut qui peut être personnalisé en précisant la valeur de
paramètres facultatifs. Comme il est impossible de tout citer, voici une simple sélection :

19
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

6. Les dictionnaires
Les dictionnaires sont des structures mutables, non ordonnées, formées d’enregistrements du
type clé :valeur Le seul moyen d’accéder à une valeur particulière est par l’intermédiaire de
sa clé. Les dictionnaires peuvent être formés :
- en évaluant l’expression dict() ou {}. On obtient le dictionnaire vide
- en délimitant par { et } une séquence de paires clé :valeur : {clé1:val1, clé2:val2,...,
clén:valn}
- en évaluant par exemple : dict([[clé1,val1],[clé2,val2],...,[clén,valn]])
- en ajoutant des paires clé :valeur à un dictionnaire existant. On a ici une différence
essentielle avec les listes, pour lesquelles il est seulement possible de modifier un
élément existant ou d’ajouter un élément supplémentaire à la fin de la liste avec la
méthode append
- en “compréhension”, par exemple D = {x:x*2 for x in range(10)}
Voici quelques méthodes applicables à un objet dic de type dictionnaire. On note ici cle une
clé et val une valeur :

20
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

7. Les ensembles
Les objets de type “ensemble” (set dans le language Python) sont des structures de données
qui modélisent la notion mathématique d’ensemble. Un ensemble (au sens Python) peut
contenir des valeurs de type quelconque, et une même valeur ne peut apparaître qu’une seule
fois. On ne peut pas y accéder par un indice : on peut juste savoir si une valeur est ou n’est
pas élément de l’ensemble. On forme un ensemble par la séquence de ses éléments (valeurs),
encadrée par { et }, ou en utilisant le constructeur set. Les objets de type “ensemble” sont
mutables. Voici quelques méthodes applicables à un objet ens de type ensemble (set). On note
elt une valeur susceptible d’appartenir ou d’être ajoutée à l’ensemble ens :

Les objets de type “ensemble” ont des méthodes pour les opérations ensemblistes usuelles :

21
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Bibliographie :
1. http://thegalsengeek.com/tag/python/
2. http://sdz.tdct.org/sdz/apprenez-a-programmer-en-python.html
3. https://openclassrooms.com/courses/apprenez-a-programmer-en-python/qu-est-ce-que-
python
4. http://master-en-informatique-python.blogspot.com/
5. http://csapstaff.ednet.ns.ca/pmannick/INFO/Python/Apprendre-Python-Ch1.pdf
6. https://fr.slideshare.net/BadrBelhajja/apprennez-programmer-en-python

22
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

CHAPITRE III:

Les sous-programmes en algorithmique :


Les fonctions et les procédures

1. Introduction
Afin de faciliter la résolution des problèmes complexes et/ou de grandes tailles, il est
souvent préférable de les décomposer en sous problèmes indépendants et de taille réduite. Ces
derniers sont à leur tour décomposés selon le besoin. La décomposition s’arrête aux sous
problèmes relativement simples à résoudre. Par la suite, on associe à chaque sous problème un
module assurant sa résolution. Un module peut être une procédure ou une fonction.
L’algorithme résolvant le problème initial présentera un ensemble d’appels aux modules
envisagés. Une telle approche s’appelle analyse modulaire.
Le recours à cette méthode de résolution présente des avantages indéniables tels que :
 Présenter des solutions claires en évitant la redondance des codes dans un programme.
 Simplifier la résolution du problème initial en supposant que les différents modules
prévus sont déjà résolus.
 Se concentrer sur la résolution d’un sous problème à la fois.
 Détecter facilement les parties à consulter ou à modifier.
 Réutiliser des modules en les définissants dans une bibliothèque.

2. Les fonctions en algorithmique


2.1. Activité 1
Ecrire un algorithme intitulé combinaison qui permet de calculer et d’afficher la combinaison
de deux entiers positifs n et p (avec n>=p et p>0).

𝑝 𝑛!
𝐶𝑛 =
𝑝! 𝑛 − 𝑝 !

Solution :
Déterminer et afficher le nombre de combinaison de p objets parmi n
Méthode de calcul :
C=F1/ (F2*F3)
n et p deux entiers avec (n>=p et p>0)

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Constations :
- on remarque la redondance de la partie calcul de la factorielle
 On peut éviter cette redondance en définissant un module permettant de calculer la
factorielle de n’importe quel entier naturel et d’appeler ce module autant de fois que
nécessaire.
- Le module crée est appelée sous-programme.
- Un sous programme peut être une procédure ou une fonction
- Une procédure est un sous programme qui peut produire plusieurs résultats alors
qu’une fonction est un sous-programme qui ne produit qu’un seul résultat de type
simple.
 Le sous programme qu’on va le crée, va calculer un résultat de type simple. Pour cela
on peut le désigner par une fonction.
2.2. Définition
Une fonction est un sous programme qui retourne une valeur d’un type identique à celui
de la fonction. Une fonction a donc un type : c’est un type simple (entier, réel, booléen,
caractère, chaîne de caractères).

Le nombre des résultats retournés par une fonction est égal à 1.

On peut distinguer deux types de fonctions :


- Fonction paramétrée.
- Fonction non paramétrée.

2.3. Vocabulaire et syntaxe

Fonction paramétrée
FONCTION Nom_F (pf1, pf2 : type1; pf3 : type2 ;…): type_résultat
VAR /* déclaration des variables locales */
Début
….. /* les instructions de la fonction */
…..
…..
Retour (Résultat)
Fin
Fonction non paramétrée
FONCTION Nom_Fonction( ): type_résultat
VAR /* déclaration des variables locales */
Début
….. /* les instructions de la fonction */
…..
…..
Retour (Résultat)
Fin

2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Solution d’Activité 1 :

Algorithme combinaison
Var
N, P, Fact, Fact1, Fact2, Fact3: entier // N, P, Fact, Fact1, Fact2 et Fact3 sont des
Objets globaux
Début
Répéter
Ecrire (″ Introduire Deux entiers ″)
Lire (N, P)
Jusqu’à (N>P) et (P>0)
Fact1  Factoriel (N) // N et P sont des paramètres effectifs
Fact2  Factoriel (P)
Fact3  Factoriel (N – P)
Fact  Fact1 / (Fact2 * Fact3)
Ecrire (″ la combinaison de ″, N, ″ par″, P, ″ est ″, Fact)
Fin

Remarque :
 Dans le corps d’une fonction on doit trouver obligatoirement l’instruction suivante :
Retour (résultat)
 L’appel d’une fonction peut se faire de différentes manières:
 Dans une instruction d’écriture :
o Exemple : Ecrire (abs(a))
 Dans une instruction d’affectation :
o Exemple : LLong(Ch)
 Dans une expression :
o Exemple : Delta carré(b)- 4*a*c
 Dans une condition :
o Exemple : Si Abs(a)>Abs(b) alors traitement1 fin si
 Dans une boucle :
o Exemple : Pour i de 1 à long(Ch) faire
Traitement1

Fin pour

2.4. Les objets locaux et les objets globaux


Un objet local est un objet déclaré dans un sous-programme et n’est pas connu qu’à
l’intérieur de celui-ci.
Un objet global est un objet déclaré dans le programme principal et utilisable par ce dernier
et les différents sous-programmes qui le forment.

2.5. Les différents types de paramètres


Les paramètres formels sont les paramètres qui se trouvent dans l’entête du sous-programme
au niveau déclaration.

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Les paramètres effectifs sont les paramètres qui figurent (dans le programme appelant) au
niveau de l’appel du sous-programme.
Remarque :
 Lors de l’appel du sous-programme les paramètres effectifs viennent remplacer les
paramètres formels. Cette substitution de paramètres s’appelle passage de
paramètres.
 Les paramètres effectifs et les paramètres formels doivent s’accorder de point de vue
nombre et ordre et doivent être de mêmes types.
 Un paramètre formel peut être déclaré par le nom de son paramètre effectif ou par un
nom différent.

3. Les procédures en algorithmique


3.1. Activité 2
Ecrire un programme intitulé affichage qui permet d’afficher un mot1 n fois et un mot2 m
fois avec mot1, n, mot2 et m sont des données.
Constatations :
D’après cette activité on remarque qu’il y a un bloc d’instructions qui se répète (au niveau
d’affichage de mot1 et celle de mot2).
Solution :
Pour éviter cette répétition, on peut isoler ce bloc d’instructions qui se répète et d’en faire un
module et d’appeler ce module autant de fois que nécessaire.
On remarque aussi que le résultat de ce module n’est pas unique, donc on ne peut pas utiliser
une fonction.
Ce pour cette raison on peut utiliser le deuxième type de sous-programme :
la procédure.

3.2. Définition
Les procédures sont des sous-programmes qui peuvent avoir plusieurs résultats.
Le nombre des résultats retournés par une procédure est appartient à [0..n]
Le seul cas ou la procédure retourne 0 résultat c’est le cas de procédure d’affichage.
Une fonction est un cas particulier de procédure.

3.3. Vocabulaire et syntaxe


Procédure paramétrée
PROCEDURE Nom_Procédure (pf1, pf2 : type1; pf3 : type2 ;…)
VAR /* déclaration des variables locales */
Début
….. /* les instructions de la procédure */
…..
Fin
Procédure non paramétrée
PROCEDURE Nom_Procédure( )
VAR /* déclaration des variables locales */
Début
….. /* les instructions de la procédure */
…..
Fin

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 &T1

Solution d’Activité2 :
ALGORITHME affichage
Var
mot1, mot2 : chaine
n, m : entier
Début
Écrire (‘’donner mot1’’), Lire (mot1)
Écrire (‘’donner mot2’’), Lire (mot2)
Répéter
Ecrire (‘’combien de fois tu veux afficher mot1’’), Lire(n)
Jusqu'à (n>0)
Répéter
Ecrire (‘’combien de fois tu veux afficher mot2’’), Lire(m)
Jusqu'à (m>0)
AFFICHE (mot1, n)
AFFICHE (mot2, m)
Fin

4. les modes de passage


Le passage de paramètres se fait par valeur ou par variable.
a) Mode de transfert par valeur :
Permet au programme (ou sous-programme) appelant de transmettre une valeur au
programme ; pour ce mode de passage, donc le paramètre formel et effectif ne désignent pas
la même zone mémoire  une modification de paramètre formel n’a aucun effet sur la
valeur du paramètre effectif.
b) Mode de transfert par variable :
Permet au programme (ou sous-programme) appelant de transmettre une valeur au
programme appelé et inversement ; pour ce mode de passage, donc le paramètre formel et
effectif désignent la même zone mémoire (la même variable)  une modification de
paramètre formel entraîne une modification sur la valeur du paramètre effectif.
Dans l’entête de la procédure, les paramètres transmis par variables sont précédées par var.
Le mot clé var est utilisé dans le cas où on veut modifier le contenu d’une variable
(paramètre formel). Ce paramètre est modifié par une instruction d’affectation ou de lecture.
Procédure nom-procédure (Var pf1 : type ; pf2 : type ; pf3 : type ; Var pf4 : type)
Var
…..
Début
Lire (pf1) //on ajoute le mot clé Var au paramètre formel pf1 dans l’entête de la
Procédure car pf1 se trouve dans une instruction de lecture.
Ecrire (pf2)
Ecrire (pf3)
pf4pf4+pf1 //on ajoute le mot clé Var au paramètre formel pf4 dans l’entête de la
Procédure car pf4 se trouve dans une instruction d’affectation.
Fin

Bibliographie :
1. http://slideplayer.fr/slide/482395/
2. http://www.kiteb.net/education/informatique/programmation/scientifiques/fiches/fiche-
sous-programmes.pdf
3. http://aidescolaire.3oloum.org/t43-les-fonctions-explication-simple-et-detaillee

5
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

CHAPITRE IV:

Les fonctions en python et la notion de complexité

1. Introduction
En Python, une fonction sert à isoler une instruction, ou un bloc d'instructions qui sera
marqué par un nom et pourra être dans un programme pour être exécuté, avec des paramètres
(arguments), qui pourront varier selon les appels. Une fonction peut renvoyer son résultat
pour être utilisé dans le programme (affection à une variable, utilisation dans une expression,
affichage …). Une fonction peut aussi définir un simple sous-programme.
En Python, les fonctions et les procédures ont la même syntaxe avec le mot clef def
suivie par le nom du sous-programme.
2. Vocabulaire et syntaxe
2.1. Le mot clef def
En Python, pour déclarer un sous-programme, on écrit le mot clef def suivi du nom de la
fonction, de la liste des paramètres formels entre parenthèses et des deux-points qui
clôturent la ligne. Lors de l’appel du sous-programme, les paramètres formels vont recevoir
les valeurs des expressions (ou paramètres effectifs) qui leur correspondront dans l’ordre
défini par la fonction.
Le mot clef return suivie d’une (des) valeur(s) permet d’indiquer la (les) valeur(s) à
retourner.
 Si le sous-programme défini a une seule valeur, après le mot clef return ; alors il
correspond bien à la définition d’une fonction en algorithmique (Le nombre des
résultats retournés par une fonction est égal à 1).
 Si le sous-programme défini a plusieurs valeurs, après le mot clef return, séparées par
des virgules ; alors il correspond bien à la définition d’une procédure en algorithmique
(Le nombre des résultats retournés par une procédure est appartient à [0..n]).
 Un sous-programme retourne 0 résultat c’est le cas de fonction d’affichage ; dans ce
cas on ne trouve pas le mot clef return.
 Quelque soit le sous-programme correspond à une fonction ou à une procédure
algorithmique, on va l’appeler en Python une fonction.

Fonction paramétrée
def nom_fonction (pf1, pf2,…):
Bloc d’instructions
return valeur1, valeur2,…
Fonction non paramétrée
def nom_fonction ( ):
Bloc d’instructions
return valeur1, valeur2,…

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

2.2. Le mot clef lambda


Python nous propose un autre moyen de créer des fonctions, des fonctions extrêmement
courtes car limitées à une seule instruction.
Pour définir une fonction, nous pouvons utiliser le mot-clé lambda comme suit :
lambda arg1, arg2,... : instruction de retour
Pour l’exemple créer une fonction qui prend un seul paramètre « y » et renvoie le carré de ce
paramètre:
>>> lambda y: y * y
>>>
D'abord, on a le mot-clé lambda suivi des arguments séparés par des virgules.
Pour appeler une fonction lambda, on doit la stocker dans une variable, par une simple
affectation :
>>> f = lambda y: y * y
>>> f(5)
25

2.3. Paramètres par défaut


En Python, il est possible de définir des valeurs par défaut pour les arguments d’une fonction.
On obtient ainsi une fonction qui peut être appelée seulement avec une portion des arguments.
Exemple :
>>>def Maximum (a,b=8):
if (a>b): return(a)
else: return(b)

>>> Maximum(6)
8

3. Variables locales et variables globales


3.1. Variables locales
Lorsque les variables sont définies à l’intérieur du corps d’une fonction, ces variables ne sont
accessibles qu’à la fonction elle-même. On parle de variables locales à la fonction. Exemple :
>>> def table (base, deb=1, fin=4):
for n in range(deb,fin+1):
print( base,'*',n,'=',base*n)
>>> table(5)
5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
>>> base
Traceback (most recent call last):
File "<pyshell#44>", line 1, in <module>
base
NameError: name 'base' is not defined
Les variables n, deb, fin et base sont des variables locales. Chaque fois que python appelle la
fonction table() il réserve pour elle un nouvel espace mémoire pour les noms qui est
inaccessible depuis l’extérieur de la fonction. Si on essaie par exemple d’afficher la valeur de
base à l’extérieur de la fonction, l’interpréteur génère un message d’erreur.

2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

3.2. Variables globales


Les variables globales sont les variables définies à l’extérieur d’une fonction. En cas de
conflit entre une variable globale et une variable locale (même nom pour les 2 variables) c’est
la variable globale qui a la priorité et qui masque donc la variable locale. Exemple:
>>> a=10
>>> def fonction (a,b):
a=a*b
return a
>>> fonction(2,3)
……………………………………………
>>> a
……………………………………………

Il y a possibilité de déclarer comme globale une variable définie à l’intérieur d’une fonction,
pour cela il faut utiliser le mot clé global avant le nom de la variable lors de l’affectation.
Exemple :
>>> def test(a=5,b=3):
global somme
somme=a+b
return somme
>>> test()
>>> somme
……………………………………
4. Gestion des erreurs
Python lève des exceptions quand il trouve une erreur dans le code (comme une erreur de
syntaxe) ou dans l'opération que vous lui demandez de faire.
Exemple :
>>>an = input () #On demande à l'utilisateur de saisir l'année
>>>an = int (an) #On essaye de convertir l'année en un entier
Si l'utilisateur donne une valeur inconvertible en entier (une lettre par exemple), le
programme s’arrête. En effet, il lève une exception et Python stoppe l'exécution du
programme. Dans ce cas, Python permet de tester une partie de code. S'il ne retourne aucune
erreur, Python continue. Sinon, on peut lui demander d'exécuter une autre action (par
exemple, redemander à l'utilisateur de saisir l'an).

 Forme minimale du bloc try


Le bloc try consiste à placer les instructions que nous souhaitons tester dans le bloc try et les
instructions à exécuter en cas d'erreur dans le bloc except.
La syntaxe est comme suit:
>>> try :
# Bloc à essayer
except :
# Bloc qui sera exécuté en cas d'erreur

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Reprenons l’exemple de test de conversion en utilisant un bloc try.


>>>an = input ()
>>>try : # Essayer de convertir an en entier
an = int (an)
except :
print (" Erreur lors de la conversion de l'année.")
 Forme plus complète du bloc try
La forme minimale ne différencie pas les exceptions qui pourront être levées dans le bloc try.
De plus, Python peut lever des exceptions qui ne désignent pas nécessairement qu'il y a eu
une erreur. Exemple :
>>>try :
resultat = numer / denom
except :
print ("Une erreur est survenue ... laquelle ?")
Plusieurs erreurs sont susceptibles d'intervenir, chacune levant une exception différente.
 NameError : l'une des variables numer ou denom n'a pas été définie.
 TypeError : l'une des variables numer ou denom ne peut diviser ou être divisée (les
chaînes de caractères ne peuvent être divisées, ni diviser d'autres types, par exemple).
 ZeroDivisionError : Si denom vaut 0, cette exception sera levée.

>>>try :
resultat = numer/ denom
except NameError :
print("La variable numer ou denom n'a pas été définie.")
except TypeError :
print("La variable numer ou denom possède un type incompatible
avec la division.")
except ZeroDivisionError :
print("La variable denom est égale à 0.")
else :
print("Le résultat est", resultat )
Dans un bloc try, else va permettre d'exécuter une action si aucune erreur ne survient dans le
bloc.
5. Documentation des fonctions
Une approche de l’écriture du logiciel de haute qualité consiste à écrire des tests pour
chaque fonction au début de son développement et à faire tourner ces tests fréquemment
durant le processus de développement.
L’utilisateur peut écrire au préalable un cahier des charges directement dans les chaînes de
documentation (docstring) du module (de la fonction, etc.). Cette manière de procéder porte le
nom de programmation dirigée par la documentation.
La syntaxe de la définition d’une fonction sera donc comme suit :
def nom_de_la_fontion(pf,…):
"""Description"""
instrutions
return résultat

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

La chaîne de caractères entre les """ est facultative. Elle permet de définir la description qui
sera donnée dans la page d’aide associée à cette fonction. Exemple :

La docstring de la fonction parfait est une copie quasiment conforme du cahier des charges
(ne pas oublier les >>> en tête des instructions à tester, y compris les résultats attendus).
Si on veut savoir ce que calcule cette fonction, on peut rajouter la ligne help(parfait).
L’exécution du programme nous ouvre alors la page d’aide de la fonction parfait:
Help on function parfait in module __main__:
parfait(n)
Détermine si un nombre est parfait,
c'est à dire somme de ses diviseurs propres
>>> parfait(100)
False
>>> parfait(496)
True

Remarque :
Le module doctest fournit un outil pour examiner un module et valider les tests immergés
dans les chaînes de documentation du programme.
L’instruction doctest.testmod() a pour effet :
– lecture du docstring et exécution des instructions commençant par >>> ;
– comparaison des résultats avec les résultats attendus ;
– affichage d’un message d’erreur s’il n’y a pas coïncidence.
6. Notion de complexité et ses classes
Il est important de pouvoir juger un algorithme (ou le programme qui en résulte) par
rapport à un autre algorithme qui résout le même problème. Il existe plusieurs critères sur
lesquels on peut se baser pour pouvoir qualifier un algorithme :
 Est-ce qu’il fait ce que nous lui demandons de faire ?
 Est-ce qu’il est muni d’une documentation qui décrit comment l’utiliser et comment il
fonctionne ?
 Est-ce que le code est facilement lisible ?
6.1. Activités
 Activité 1 : Proposer en Python deux programmes différents pour vérifier la
primalité d’un entier n?
 Activité 2 : Proposer en Python deux programmes différents pour calculer xn?
5
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Afin de réaliser ces activités, on a besoin de mesurer le temps d’exécution de chaque


programme. En Python, pour mesurer le temps d'exécution d’un programme nous pouvons
simuler un chronomètre :
 on le déclenche juste avant le début du programme,
 on l'arrête juste après la fin du programme,
 le temps écoulé entre les deux pressions est la durée qui nous intéresse.
En Python, on peut simuler un chronomètre grâce au module time. Exemple:
from time import *
debut = time() # on déclenche le chronomètre
# votre programme
fin = time() # on arrête le chronomètre
print(’Temps écoulé:’, fin - debut, ’ secondes’)

 Solution Activité 1 :
Considérons la fonction est_premier(n) qui permet de déterminer si l'entier naturel n est
premier.
Programme naïf : ce programme consiste à diviser n par tous les entiers qui lui sont
inférieurs. Si un de ces entiers est un diviseur de n, n n'est pas premier.
from time import *
def est_premier(n) :
a=time()
for i in range(2, n):
if n% i == 0 :
print(time()-a, "sec")
return (False)
print(time()-a, "sec")
return(True)
print(est_premier(2**31-1))
Résultat d’exécution:
>>> 554.3090000152588 sec
True
Programme rapide : Nos connaissances en arithmétique nous assurent que si nombre n'est
pas premier, un de ses diviseurs est inférieur à n. La fonction est_premier devient alors :
from time import *
def est_premierrapide(n) :
a=time()
for i in range(2, int(n**(1/2))+1) :
if n% i == 0 :
print(time()-a, "sec")
return (False)
print(time()-a, "sec")
return(True)
print(est_premierrapide(2**31-1))
Résultat d’exécution:
>>> 0.009999990463256836 sec
True

6
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 Solution Activité 2 :
Considérons la fonction puissance(x,n) qui calcule xn.
Programme naïf : xn = x*x*………….*x

from time import * n fois


def puissance(x,n) :
a=time()
r=1
for i in range(1, n+1):
r=r*x
print(time()-a, "sec")
return(r)
puissance(3,2**20-1)
Résultat d’exécution:
>>> 107.77800011634827 sec
Programme rapide :

from time import *


def puissancerapide(x,n) :
a=time()
r=1
while n>0:
if n%2!=0:
r=r*x
n=n//2
x=x*x
print(time()-a, "sec")
return(r)
puissancerapide(3,2**20-1)
Résultat d’exécution:
>>> 1.3240001201629639 sec

 Conclusion :
Dans l’étude de complexité d’un algorithme on ne mesure pas la durée en heures, minutes,
secondes, ...:
 cela impliquerait d'implémenter les algorithmes qu'on veut comparer ;
 de plus, ces mesures ne seraient pas appropriées car le même algorithme sera plus
rapide sur une machine plus puissante.
L’étude de complexité consiste donc à utiliser des unités de temps abstraites proportionnelles
au nombre d'opérations effectuées.
On pourra par la suite adapter ces quantités en fonction de la machine sur laquelle
l'algorithme s'exécute.

7
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

6.2. Définitions
La complexité d’un programme est généralement en relation directe avec ses
performances. Il s’agit du temps d’exécution et de l’espace mémoire nécessaires pour
l’exécution ; ces deux critères désignent complexité temporelle et complexité spatiale.
 Complexité temporelle : c'est le nombre d'opérations élémentaires effectuées par une
machine qui exécute le programme et le temps nécessaire pour chaque opération.
 Complexité spatiale : c'est le nombre de positions mémoire utilisées par une machine
qui exécute le programme.

Ces deux complexités dépendent de la machine utilisée mais aussi des données traitées. En
pratique, toutes les opérations élémentaires n'ont pas le même temps d'exécution : une
multiplication demande plus de temps qu'une addition. Pour simplifier, on ne comptera ici que
le nombre d'opérations à réaliser sans tenir compte de leurs différences.
N.B. : On va considérer dans ce cours la complexité temporelle car la complexité spatiale est
étroitement liée aux caractéristiques techniques de l’ordinateur sur lequel le programme
s’exécute. De plus, on cherche à déterminer une mesure pour la complexité temporelle
indépendamment des caractéristiques techniques de l’ordinateur, du langage de
programmation, du compilateur et des détails d’implémentation. Donc on ne peut utiliser une
unité de temps (par exemple la milliseconde) pour exprimer la complexité temporelle car ce
genre d’unité est étroitement lié aux caractéristiques techniques de la machine. Il est
important que l’unité utilisé indique la complexité de l’algorithme utilisé indépendamment de
la machine sur laquelle sera exécuté le programme résultant.

6.3. Types de complexité temporelle


En termes plus concrets, la complexité temporelle de l’algorithme est la mesure du nombre
d’opérations fondamentales (opérations arithmétiques, affectations, comparaisons) qu’il
effectue sur un jeu de données. Elle est exprimée comme une fonction de la taille n des
données. On s'intéresse:
 La complexité au pire: temps d'exécution maximum, le cas le plus défavorable.
 La complexité au meilleur: temps d'exécution minimum, le cas le plus favorable.
 La complexité moyenne: moyenne des temps d'exécution.
La complexité au pire est le type le plus utilisé, car on veut borner le temps d'exécution.

Notations:
 Dn : l’ensemble des données de taille n
 T(n) : le nombre d’opérations sur un jeu de données de taille n

8
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

6.4. Calcul du coût d’un programme


Calculer le coût d’un programme revient à calculer le nombre d’opérations effectuées en
fonction de la taille des données. Pour déterminer le coût d’un algorithme, on se fonde en
général sur le modèle de complexité suivant :
 Une affectation, une comparaison ou l’évaluation d’une expression arithmétique (+,-
,/,*,//,%,**) ayant en général un faible temps d’exécution considéré comme l’unité de
mesure du coût d’un algorithme.
 Le coût des instructions A et B en séquence est la somme des coûts de l’instruction A et
de l’instruction B.
 Le coût d’un test if
if condition: A
else: B
Le coût d’un test est égal au maximum des coûts des instructions A et B, plus le temps
d’évaluation de l’expression condition.
 Le coût d’une boucle for
for i in range(n):
A
Le coût d’une boucle for est égal au nombre de répétitions multiplié par le coût du bloc
d’instructions A. Quand le coût de A dépend de la valeur de i, le coût total de la boucle est
la somme des coûts de p pour chaque valeur de i.
 Le cas d’une boucle while
while condition:
A
Le cas d’une boucle while est plus complexe à traiter puisque le nombre de répétitions
n’est en général pas connu a priori. On peut majorer le coût de l’exécution de la boucle par
le nombre de répétitions effectuées.

Exemple: Calculer la factorielle d’un entier n

Le coût de l’algorithme = Nombre total d’opérations


= 1 Affectation + (n-1) *( 1 affectation + 1 multiplication)+1 renvoi
T( n) = 1+ (n-1)*2+1 = 2* n

6.5. Notion de Landau O


Il faut noter que dans le calcul de la complexité d’un algorithme ce qui est important c’est
l’ordre de grandeur du nombre d’opérations fondamentales. Ce qui nous intéresse c’est de
voir comment évolue la complexité en fonction de la taille de donnée (n), et en particulier
quand la donnée (n) devient très grande.

9
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Soit T(n) est le nombre d’opérations effectuées. On dit que T(n) est en O(f(n)) s’il existe deux
constantes positives c et n0 telles que T(n) ≤ c × f(n) pour tout n>n0. Où f est en générale une
combinaison de polynômes, exponentielles ou logarithmes.

𝑻 𝒏 = 𝜪(𝒇 𝒏 ) 𝒔𝒊 ∃𝒏𝟎 , ∃𝒄 ≥ 𝟎, ∀𝒏 > 𝒏𝟎 , 𝒐𝒏 𝒂 𝑻(𝒏) ≤ 𝒄 × 𝒇(𝒏)


Signification :
Pour toutes les grandes entrées (n>n0), on est assuré que l’algorithme ne prend pas plus de
c × f(n) étapes.
Exemple : T(n)=c1*n2 + c2*n
c1*n2 + c2*n ≤ c1*n2 + c2*n2 ≤ (c1+c2)*n2 pour tout n>1
T(n) ≤ c*n2 où c=(c1+c2) et n0=1
Donc, T(n) est en O(n2)
Les règles de la notation O :
 Les termes constants :
Ο(c) = Ο(1)
 Les constantes multiplicatives sont à négliger :
Ο c × T = 𝑐 × Ο 𝑇 = Ο(𝑇)
 L'addition est réalisée en prenant le maximum :
Ο 𝑇1 + Ο 𝑇2 = Ο 𝑇1 + 𝑇2 = max⁡ (Ο 𝑇1 , Ο 𝑇2 )
 La multiplication reste inchangée :
Ο 𝑇1 × Ο 𝑇2 = Ο 𝑇1 × 𝑇2
Exemple : Supposant que le temps d'exécution d’un algorithme est décrit par la fonction
T(n) = 7n2+5n+13, Calculer O(T(n))?
O(T(n)) = O(7 n2 + 5n + 13) = O(max (7 n2, 5n, 13)) = O(7 n2) = O (n2)
6.6. Classes de complexité
Classe Notation O Exemple
Constante O(1) Accéder au premier élément d'un ensemble de données
Linéaire O(n) Parcourir un ensemble de données
Logarithmique O(log(n)) Diviser un jeu de données en deux parties égales, puis
diviser ces moitiés en deux parties égales, etc.
Quasi-linéaire O(n log(n)) Diviser répétitivement un jeu de données en deux et
combiner les solutions partielles pour calculer la solution
générale
Quadratique O(n2) Parcourir un jeu de données en utilisant deux boucles
imbriquées
Polynomiale O(nP) Parcourir un jeu de données en utilisant P boucles
imbriquées
Exponentielle O(an) Générer tous les sous ensembles possibles d'un jeu de
données

10
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

L’évolution du temps de calcul en fonction de n pour complexités usuelles :


On suppose qu’on dispose d’un ordinateur capable de réaliser 109 opérations/seconde.

6.7. Calcul de la complexité temporelle


Il n’existe pas de méthodologie systématique permettant pour un algorithme quelconque
de compter les opérations élémentaires. Néanmoins des règles usuelles sont fréquemment
admises par la communauté des informaticiens qui les utilise pour évaluer la complexité
temporelle. Parmi ces règles, on peut citer les cas suivants:
o Cas d'une instruction simple (écriture, lecture, affectation) : Le temps d'exécution
de chaque instruction simple est O(1).
o Cas d'une suite d'instructions simples: Le temps d’exécution d'une séquence
d'instruction est déterminé par la règle de la somme. C'est donc le temps de la
séquence qui a le plus grand temps d’exécution:
Ο 𝑇 = Ο 𝑇1 + 𝑇2 = max⁡ (Ο 𝑇1 , Ο 𝑇2 .
Traitemen1 T1(n)
T(n) = T1(n) + T2(n)
Traitemen2 T2(n)
Exemple:
def Permutation ( i, j):
tmp = i #O(T1) = O (1)
i = j #O(T2) = O (1)
j = tmp #O(T3) = O (1)
O(T) = O (T1 + T2 + T3) = O (1)
o Cas d'un traitement conditionnel : Le temps d'exécution d'une instruction if est le
temps d’exécution des instructions exécutées sous condition, plus le temps pour
évaluer la condition. Pour une alternative, on se place dans le cas au pire.
if <condition> :
Traitement1
else:
Traitement2
O(Tcondition) + max(O(TTraitement1) , O(TTraitement2))

11
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

o Cas d'un traitement itératif : Le temps d’exécution d'une boucle est la somme du
temps pour évaluer le corps et du temps pour évaluer la condition. En général, ce
temps est la multiplication du nombre d'itérations de la boucle par le plus grand temps
possible pour une exécution du corps.

Boucle for Boule while

for i in range(indDeb,indFin+1): while <condition> :


Traitement Traitement
𝐢𝐧𝐝𝐅𝐢𝐧 Supposant que m est le nombre d’itérations
𝐎(𝐓𝐭𝐫𝐚𝐢𝐭𝐞𝐦𝐞𝐧𝐭 )
𝐢=𝐢𝐧𝐝𝐃𝐞𝐛 𝐦 ∗ 𝐎 𝐓𝐜𝐨𝐧𝐝𝐢𝐭𝐢𝐨𝐧 + 𝐎 𝐓𝐓𝐫𝐚𝐢𝐭𝐞𝐦𝐞𝐧𝐭
= 𝐦𝐚𝐱 𝐎 𝐓𝐭𝐫𝐚𝐢𝐭𝐞𝐦𝐞𝐧𝐭 𝐢𝐧𝐝𝐃𝐞𝐛≤𝐢≤𝐢𝐧𝐝𝐅𝐢𝐧 = 𝐦 ∗ 𝐦𝐚𝐱(𝐎 𝐓𝐜𝐨𝐧𝐝𝐢𝐭𝐢𝐨𝐧 , 𝐎 𝐓𝐓𝐫𝐚𝐢𝐭𝐞𝐦𝐞𝐧𝐭

Pour calculer la complexité d'un programme :


1. on calcule la complexité de chaque partie du programme;
2. on combine ces complexités conformément aux règles qu'on vient de voir ;
3. on simplifie le résultat grâce aux règles de simplifications suivantes:
 on remplace les constantes multiplicatives par 1,
 on annule les constantes additives,
 on conserve le terme dominant.

Exemple: T(n)=5n3-6n2+4
 On remplace les constantes multiplicatives par 1,
1n3-1n2+4
 On annule les constantes additives,
1n3-1n2
 On conserve le terme dominant,
n3-n2
 Solution : T(n) = O(n3)
Exercice : Calcul de la complexité de la fonction factorielle

La complexité de la fonction : O(1)+O(n)*O(1)+O(1) = O(n)

12
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Des cas de complexité fréquemment utilisés:

Bibliographie :
1. https://s03a5674be0a5c3e6.jimcontent.com/download/ve
2. https://issuu.com/jeebeezebee/docs/223267-apprenez-a-programmer-en-pyt
3. https://openclassrooms.com/courses/apprenez-a-programmer-en-python/pas-a-pas-
vers-la-modularite-1-2
4. https://fr.wikibooks.org/wiki/Programmation_Python/Fonctions_originales
5. https://fr.slideshare.net/BENSAAOUD/1-analyseetmesuredesperformances
6. http://docplayer.fr/7041493-Structures-de-donnees-et-algorithmes-fondamentaux.html
7. https://www.academia.edu/6152917/08_02_2014_1_CHAPITRE_4_Complexit%C3%
A9_des_algorithmes_La_O-Notation_Partie_1
8. http://www.fsg.rnu.tn/imgsite/cours/complexit%C3%A9.pdf
9. https://fr.slideshare.net/sanaaroussi3/chapitre-ii-complexit-et-optimali

13
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

CHAPITRE V:

LA RECURSIVITE

1. Définition
Un algorithme est dit récursif s'il est représenté en fonction de lui-même. La récursivité
est un principe puissant permettant de définir une entité à l'aide d'une partie de celle-ci. Alors,
chaque appel successif travaille sur un ensemble d'entrées toujours plus affinée, en se
rapprochant de plus en plus de la solution d'un problème.
Prenons un exemple classique : le calcul de la factorielle. On définit, pour n ≥ 0,
𝑛
n! = 𝑖=1 𝑖 . Informatiquement, on peut donc définir la fonction factorielle selon
l’environnement de développement Python comme suit:

def Fact(n) :

f=1
for i in range(1,n+1) :
f=f*i
return(f)

Une autre définition mathématique classique de la factorielle se fait par récurrence :

1 𝑠𝑖 𝑛 = 0
𝑛! =
𝑛 ∗ 𝑛 − 1 ! 𝑠𝑖𝑛𝑜𝑛
En reprenant quasiment mot par mot cette dernière définition, on obtient la fonction Python
suivante :
def Fact_rec(n) :

if n==0 :
return(1)
else :
return(n*Fact_rec(n-1))

2. Evolution d’un appel récursif


La réalisation d'un appel récursif se compose par deux phases, la phase de descente et la
phase de la remontée.

2.1. Phase de descente


Dans cette phase, chaque appel récursif réalise à son tour un appel récursif. Cette phase
finit lorsque l'un des appels abouti à une condition terminale. Dans le traitement de cette
condition la fonction doit retourner une valeur à la place de faire un autre appel récursif.

1
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exemple:
4!= Fact_rec(4)=4*Fact_rec(3)
Fact_rec(3)=3*Fact_rec(2)
Fact_rec(2)=2*Fact_rec(1) Condition terminale :
Fact_rec(1)=1*Fact_rec(0) => n = = 0
Fact_rec(0) = 1

2.2. Phase de la remontée


En arrivant à la condition terminale, on démarre la phase de la remontée. Cette phase se
poursuit jusqu'à ce que l'appel initial soit achevé, ce qui termine le processus récursif.
Exemple:

3. Les types de récursivité

3.1. La récursivité simple


La récursivité simple est définit lorsqu’un algorithme contient un seul appel récursif dans
son corps. Exemple de la récursivité simple est la fonction factorielle (Fact_rec).

3.2. La récursivité multiple


La récursivité multiple est définit lorsqu’un algorithme est formé de plusieurs appels
récursifs dans son corps. Exemple de la récursivité multiple est le calcul du nombre de
combinaisons par la relation de Pascal :
𝑝 1 𝑠𝑖 𝑝 = 0 𝑜𝑢 𝑝 = 𝑛
𝐶𝑛 = 𝑝 𝑝−1
𝐶𝑛−1 + 𝐶𝑛−1 𝑠𝑖𝑛𝑜𝑛
def Combinaisons(n,p) :

if p==0 or p==n:
return(1)
else :
return(Combinaisons(n-1,p)+ Combinaisons(n-1,p-1))

3.3. La récursivité mutuelle


Des algorithmes sont dits mutuellement récursifs s’ils dépendent les unes des autres.

2
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exemple : la définition de la parité d'un entier peut être représentée de la façon suivante :

𝑣𝑟𝑎𝑖 𝑠𝑖 𝑛 = 0 𝑓𝑎𝑢𝑥 𝑠𝑖 𝑛 = 0
𝑝𝑎𝑖𝑟 𝑛 = 𝑒𝑡 𝑖𝑚𝑝𝑎𝑖𝑟 𝑛 =
𝑖𝑚𝑝𝑎𝑖𝑟 𝑛 − 1 𝑠𝑖𝑛𝑜𝑛 𝑝𝑎𝑖𝑟 𝑛 − 1 𝑠𝑖𝑛𝑜𝑛

def pair(n) :

if n==0 :
return(True)
return(impair(n-1))

def impair(n) :

if n==0 :
return(False)
return(pair(n-1))

3.4. La récursivité imbriquée


La récursivité imbriquée est définit lorsque il s’agit d’un appel récursif à l'intérieur d'un
autre appel récursif. Exemple de la récursivité imbriquée est la fonction d’Ackermann définie
comme suit :

𝑛+1 𝑠𝑖 𝑚 = 0
𝐴 𝑚, 𝑛 = 𝐴 𝑚 − 1,1 𝑠𝑖 𝑚 > 0 𝑒𝑡 𝑛 = 0
𝐴 𝑚 − 1, 𝐴 𝑚, 𝑛 − 1 𝑠𝑖𝑛𝑜𝑛
En Python:

def Ackermann(m,n) :

if m==0 :
return(n+1)
if n==0 :
return(Ackermann(m-1,1))
return(Ackermann(m-1, Ackermann(m,n-1)))

>>> Ackermann(3,4)
125

Limites de la récursivité : On remarque lors de l’appel à Ackermann(100,0) produit un


message d’erreur dont l’intitulé est RuntimeError : maximum recursion depth exceeded. En d’autres
termes, le nombre maximal d’appels de fonctions imbriqués a été atteint. En Python, ce niveau
est fixé à 1000. Cette valeur arbitraire peut-être augmentée mais elle est là pour éviter un
dépassement de capacité de la mémoire réservée. Dans ce cas, il vaut mieux donc utiliser une
méthode itérative.

3
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

4. Complexité d’une fonction récursive


Pour estimer la complexité en temps d’une fonction récursive, on explicite la « taille » n
de l’argument, et on note T(n) le nombre d’opérations pour l’évaluation de la fonction avec
un argument de taille n (ou encore le coût de la fonction).
On établit une relation de récurrence satisfaite par T(n), pour en déduire l’expression de T(n)
et son ordre de grandeur O(n) lorsque n  .
Par la suite, la complexité d’une fonction récursive se calcule par la résolution d’une équation
de récurrence en éliminant la récurrence par substitution de proche en proche ou en utilisant
des formes mathématiques.
Remarque : Résolution des récurrences des algorithmes
La résolution des relations de récurrence déduites des algorithmes récurrents se fait selon trois
cas fréquents :

 Suite arithmétique :
𝑐𝑜𝑛𝑠𝑡𝑎𝑛𝑡𝑒 𝑠𝑖 𝑛 = 0
𝑇 𝑛 = 𝑇 𝑛 = 𝑟 ∗ 𝑛 + 𝑇(0)
𝑇 𝑛 − 1 + 𝑟 𝑠𝑖𝑛𝑜𝑛

 Suite arithmético-géométrique :
𝑐𝑜𝑛𝑠𝑡𝑎𝑛𝑡𝑒 𝑠𝑖 𝑛 = 0
𝑇 𝑛 = 𝑇 𝑛 = 𝑎𝑛 ∗ 𝑇 0 − 𝑟 + 𝑟
𝑎 ∗ 𝑇 𝑛 − 1 + 𝑏 𝑠𝑖𝑛𝑜𝑛
𝑏
Tel que : 𝑟 =
1−𝑎
 Relation de récurrence de forme :
𝑛
𝑇 𝑛 = 𝑎∗𝑇 − 𝑓 𝑛 𝑎𝑣𝑒𝑐 𝑓 𝑛 = 𝑐 ∗ 𝑛𝑘
𝑏
𝑘
o Si 𝑎 > 𝑏 𝑇 𝑛 = Ο(𝑛𝑙𝑜𝑔 𝑏 (𝑎) )
𝑘
o Si 𝑎 = 𝑏 𝑇 𝑛 = Ο(𝑛𝑘 𝑙𝑜𝑔𝑏 (𝑛))
𝑘
o Si 𝑎 < 𝑏 𝑇 𝑛 =Ο 𝑓 𝑛 = Ο(𝑛𝑘 )

Exemple : La fonction factorielle. On a déjà dit que n! se calculait en complexité linéaire


avec la fonction fact_rec. Vérifions-le.

Si n est nul, il n’y a rien à faire d’autre que de retourner 1, ce qui se fait avec une opération
élémentaire. Sinon, il faut multiplier le résultat de fact_rec(n-1) par n, ce qui prend donc 1
appel récursif, et 1 opération arithmétique, soit 2 opérations élémentaires.

On a donc :

1 𝑠𝑖 𝑛 = 0
𝑇 𝑛 =
2 + 𝑇 𝑛 − 1 𝑠𝑖𝑛𝑜𝑛
Il s’agit d’une suite arithmétique de raison 2, dont le terme générale est 2n. On vérifie que
T(n) = 2n + 1 est la solution de cette récurrence, on déduit donc que T(n) = O(n)

4
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exercice : On considère la suite (un) suivante, qui calcule une approximation de 3 :

On explique ici comment calculer le coût d’une fonction récursive, à savoir le nombre
d’opérations élémentaires qu’elle effectue.

def u(n):
if n == 0:
return 2.
else:
x = u(n-1)
return 0.5 * (x + 3. / x)

Evaluons le nombre d’opérations arithmétiques (addition, multiplication et division) et


élémentaires qu’elle effectue.
Si n désigne la valeur de son argument, notons T(n) ce nombre d’opérations. En suivant la
définition de la fonction u, on obtient les deux équations suivantes :

1 𝑠𝑖 𝑛 = 0
𝑇 𝑛 =
𝑇 𝑛 − 1 + 5 𝑠𝑖𝑛𝑜𝑛

En effet, dans le cas n = 0, il n’y a rien à faire d’autre que de retourner 1. Et dans le cas n > 0,
on fait d’une part un appel récursif sur la valeur n−1, d’où T(n−1) opérations avec une
opération d’affectation, puis trois opérations arithmétiques (une multiplication, une addition et
une division) avec une opération de return. Il s’agit d’une suite arithmétique de raison 5, dont
le terme général est : T(n) = 5n+1

Le nombre d’opérations arithmétiques effectuées par la fonction u est donc proportionnel à n.


Il s’agit donc, d’une complexité linéaire : O(n).

Si en revanche on avait écrit la fonction u plus naïvement, avec deux appels récursifs u(n-1),
c’est-à-dire :
def u(n):
if n == 0:
return 2.
else:
return 0.5 * (u(n-1) + 3. / u(n-1))

5
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Alors les équations définissant T(n) seraient les suivantes :

1 𝑠𝑖 𝑛 = 0
𝑇 𝑛 =
𝑇 𝑛 − 1 + 𝑇 𝑛 − 1 + 4 𝑠𝑖𝑛𝑜𝑛

En effet, il convient de prendre en compte le coût T(n − 1) des deux appels à u(n-1). Il s’agit
maintenant d’une suite arithmético-géométrique, dont le terme général est : T(n) = 5*2n − 4.
Il s’agit donc, d’une complexité exponentielle : O(2n).

5. Conclusion sur la récursivité


On a vu dans ce cours les avantages et les inconvénients de la récursivité.

- Inconvénients :
 Il faut faire attention à ne pas faire trop d’appels récursifs imbriqués
 Il faut faire attention à ne pas faire plusieurs fois les même calculs, sous peine
de voir la complexité exploser.
 Lorsque deux solutions sont équivalentes, l’une en récursif, l’autre en itératif,
il est en général préférable d’utiliser la version itérative.
- Avantages :
 Dans l’ensemble, il est plus facile de prouver un algorithme récursif que son
équivalent itératif.
 L’écriture d’un programme récursif est souvent plus claire (plus
mathématique), que son équivalent itératif.
 Parfois, et c’est là où la récursivité est vraiment importante, il n’est pas du tout
aisé de transformer un algorithme récursif en algorithme itératif. C’est en
général le cas des algorithmes « diviser pour régner ».

Bibliographie :

1. https://fr.slideshare.net/chahrawoods/cours-algorithmique-et-complexite-complet
2. https://fr.slideshare.net/sanaaroussi3/chapitre-iii-rcursivit-et-paradigme-diviser-pour-
rgner
3. http://prepa.blois.free.fr/INFO/wa_files/INF0_MP_01.pdf
4. https://fr.scribd.com/doc/46954197/Calcul-Numerique-Applique-Maths-Algorithme-
Edition-Edp-Sciences

6
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

CHAPITRE Vi:

Manipulation des itérables en python

1. Introduction
Dans ce chapitre, nous allons manipuler des algorithmes sur deux traitements très utiles en
informatique qui sont la recherche et le tri. Nous allons les appliquer pour des itérables en
Python.

2. Les méthodes de recherche


Il y a, essentiellement, deux méthodes de recherche d’un élément dans un itérable (liste,
chaîne de caractères, …) ; et qui sont : la recherche séquentielle et la recherche dichotomique.
Nous allons appliquer ces deux méthodes, en particulier, pour les listes mais ça peut être
généralisé pour importe quel type d’itérable.

2.1. Recherche séquentielle


 1ère solution
On cherche à déterminer si une liste contient une certaine valeur. On ne va pas
nécessairement examiner tous les éléments de la liste, car on souhaite interrompre le parcours
dès que l’élément est trouvé. Une première solution se base à une boucle while :
def appartient(x, a):

…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
………………………………………………………………………………………………………………………………………………………………….

 2ème solution
On peut procéder autrement en utilisant la construction return à l’intérieur de la boucle for
pour interrompre son exécution.
def appartient(x, a):
for y in a:
if y == x:
return True
return False

1
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

 3ème solution
On va maintenant écrire une fonction de recherche légèrement différente, qui renvoie le
premier indice d’apparition de x dans la liste s. On utilise alors enumerate pour parcourir
simultanément les indices et les valeurs correspondantes. La construction return fait sortir de la
fonction dès que la valeur x est trouvée.
Si on sort de la boucle, on renvoie None pour signaler un échec de la recherche.
def indice(x, s):
for i, y in enumerate(s):
if y == x:
return i
return None
 Complexité de la recherche séquentielle
On note que dans le pire des cas, les fonctions appartient et indice précédentes parcourent
toute la liste et effectuent donc n comparaisons, où n est la longueur de la liste. Il s’agit donc,
d’une complexité linéaire : O(n).

2.2. Recherche dichotomique


Dans certains cas, la recherche d’un élément dans une liste peut être réalisée de manière plus
efficace que la méthode séquentielle par exemple lorsque la liste est triée. Dans ce cas, la
méthode de recherche dichotomique s’impose. L’idée consiste à découper la liste en deux par le
milieu puis de voir si la valeur x doit être recherchée dans la côté gauche ou droite. En effet, il
suffit pour cela de la comparer avec la valeur centrale. Puis, on répète le processus sur la portion
sélectionnée.

Exemple :
On suppose par exemple que l’on cherche la valeur x = 9 dans la liste a= [1, 3, 5, 6, 9, 12, 14].
La recherche s’effectue ainsi :

Seules trois comparaisons ont été nécessaires pour trouver la valeur. C’est une application du
principe "diviser pour régner".

2
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Le code est :
def recherche_dichotomique(x, a):
"""
renvoie, si elle existe, la position d'une occurrence de x dans a
supposé trié, et None sinon
"""
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
……………………………………………………………………………………………………………

 Complexité de la recherche dichotomique


La méthode de recherche dichotomique est de diviser le problème en deux sous-problèmes. Il
s’agit donc, d’une complexité logarithmique : O(log(n)), où n est la longueur de la liste.
Pour conclure, la complexité de la recherche dichotomique est O(log(n)), alors que celle de la
recherche séquentielle est O(n). Comme nous avons vu, la méthode de recherche dichotomique
ne s’applique que pour des données déjà triées.

2.3. Application : Recherche d’un mot dans un texte


Un problème classique en informatique consiste à rechercher, non pas une seule valeur, mais
une séquence de valeurs dans une liste. Cela revient à chercher une occurrence d’une liste dans
une autre ou, pour les chaînes de caractères, une occurrence d’un mot dans un texte. On souhaite
donc écrire une fonction recherche_mot qui, étant donnés deux chaines m et t, détermine la
position de la première occurrence de m dans t, si elle existe, et qui renvoie None sinon.
Ainsi, pour les chaines m= ‘’bonbon’’ et t=’’quel bon bonbon’’, recherche_mot renvoie 9 :
On effectue la recherche avec une boucle for, qui va considérer toutes les positions possibles
pour le mot m, c’est-à-dire tous les indices i entre 0 et len(t) - len(m), au sens large.

def recherche_mot(m, t):


for i in range(len(t) - len(m)+1):

On teste si le mot m apparaît à la position i avec une seconde boucle, qui compare les
caractères de m et de t un à un. On utilise une variable j pour cela et on s’arrête, soit lorsque j
atteint len(m), soit lorsque les caractères diffèrent :

j = 0
while j < len(m) and m[j] == t[i + j]:
j += 1

3
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Une fois sorti de la boucle while, on a reconnu le mot m à la position i si et seulement si


j == len(m), auquel cas on renvoie i. On interrompt ainsi l’exécution de la fonction dès la
première occurrence trouvée :
if j == len(m):
return i

Sinon, on passe à la valeur suivante de i. Si on parvient à la fin de la boucle for principale,


c’est qu’il n’y a pas d’occurrence de m dans t, ce que l’on signale en renvoyant None :
return None

Le code complet :
def recherche_mot(m, t):
"""
renvoie, si elle existe, la position de la première occurrence du mot
m dans le texte t et renvoie None sinon
"""
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………………………………………………………………………
…………………………………………………………………………………………………………….

3. Les méthodes de tri


Si on définit le mot tri selon le dictionnaire, on trouve qu’il s’agit de l’opération consistant à
''répartir en plusieurs classes selon certains critères un ensemble d’éléments''.
En informatique, un algorithme de tri est un algorithme qui permet d’organiser une collection
d’objets selon un ordre déterminé. Les objets à trier font partie d’un ensemble mené d’une
relation d’ordre (de manière générale un ordre total).
Il existe plusieurs algorithmes de tri. Nous allons étudier cinq algorithmes : tri par sélection,
tri à bulles, tri par insertion, tri par fusion et tri rapide.

3.1. Tri par sélection


 Principe :
Le tri par sélection est l'algorithme de tri le plus simple. Il s’agit de trouver l'emplacement de
l'élément le plus petit (grand) de la liste si on va trier en ordre croissant (décroissant). Une fois
cet emplacement trouvé, on compare son contenu avec L[0] et s'ils sont différents, on permute
l'élément de l'emplacement trouvé par l'élément de la première position L[0]. Après ce parcours
le premier élément est bien placé.

4
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

On recommence le même procédé pour le reste de la liste (L[1],..,L[n-1]), ainsi on recherche


le plus petit (grand) élément de cette nouvelle partie et on l'échange éventuellement avec L[1]. Et
ainsi de suite ... jusqu'à la dernière partie de la liste formée par les deux derniers éléments
(L[n-2], L[n-1]).
 Exemple :
On se propose d’utiliser la méthode de tri par sélection pour trier une liste L en ordre décroissant.
Considérons la liste L contenant les 7 éléments suivants :

L 14 2 47 10 18 13 5
0 1 2 3 4 5 6
Etape 1
- Chercher la valeur maximale dans L (de l’élément numéro 1 à l’élément numéro 7 : cette
valeur étant 47 et son indice est 2).
- Permuter l’élément d’indice 2 avec l’élément d’indice 0.
L 47 2 14 10 18 13 5
0 1 2 3 4 5 6

Etape 2
- chercher la valeur maximale dans L (de l’élément numéro 2 à l’élément numéro 7 : cette valeur
étant 18 et son indice est 4).
- Permuter l’élément d’indice 1 avec l’élément d’indice 4.
L 47 18 14 10 2 13 5
0 1 2 3 4 5 6

Remarque :

La liste comporte une partie triée composée de deux premiers éléments et une partie non encore
triée qui comporte le reste des éléments de L.

L 47 18 14 10 2 13 5
0 1 2 3 4 5 6

Etape 3
- chercher la valeur maximale dans L (de l’élément numéro 3 à l’élément numéro 7 : cette valeur
étant 14 et son indice est 2).
- Puisque la valeur maximale correspond au premier élément de la partie non triée de la liste L,
nous n’avons pas besoin de réaliser l’action de permutation.

L 47 18 14 10 2 13 5
0 1 2 3 4 5 6

Partie triée Partie non triée

Etape 4
- chercher la valeur maximale dans L (de l’élément numéro 4 à l’élément numéro 7 : cette valeur
étant 13 et son indice est 5).
- Permuter l’élément d’indice 3 avec l’élément d’indice 5.

5
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Partie non triée


L 47 18 14 13 2 10 5
0 1 2 3 4 5 6
Partie triée

Etape 5

- chercher la valeur maximale dans L (de l’élément numéro 5 à l’élément numéro 7 : cette valeur
étant 10 et son indice est 5).
- Permuter l’élément d’indice 4 avec l’élément d’indice 5.

Partie non triée


L 47 18 14 13 10 2 5
0 1 2 3 4 5 6
Partie triée

Etape 6

- chercher la valeur maximale dans L (de l’élément numéro 6 à l’élément numéro 7 : cette valeur
étant 5 et son indice est 6).
- Permuter l’élément d’indice 5 avec l’élément d’indice 6.

L 47 18 14 13 10 2 5
0 1 2 3 4 5 6
Liste triée

 Code en python : ordre décroissant


def tri_selection(L) :
n = len(L)
for j in range(0, n-1):
indiceDuMin=j
for k in range(j+1,n) :
if L[k]>L[indiceDuMin] :
indiceDuMin=k
if indiceDuMin !=j :
L[j],L[indiceDuMin]=L[indiceDuMin],L[j]
return(L)

3.2. Tri à bulles


 Principe :
Le tri à bulles, en ordre croissant (décroissant), consiste à faire remonter le plus grand (petit)
élément de la liste en comparant les éléments successifs. C'est-à-dire qu'on va comparer le 1 er et
le 2ième élément, s'ils ne sont pas dans le bon ordre, on les permute, on passe ensuite au 2ième et
3ième, puis au 3ième et 4ième et ainsi de suite jusqu'au (n-1)ième et nième éléments.
A la fin du premier parcours, on aura poussé le plus grand (petit) élément vers sa place finale qui
est le nième élément. On recommence cette opération en parcourant de 0 à n-2 puis de 0 à n-3 et
ainsi de suite. On arrête quand la partie à trier est réduite à un seul élément ou que la liste est
devenue trié et dans ce cas on doit avoir un indicateur qui donne cette information. En effet,

6
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

l'idée est de vérifier si lors du dernier parcours aucune permutation n'a été faite ce qui signifie
que la liste est devenue trié.
 Exemple :
On se propose d’utiliser la méthode de tri à bulles pour trier une liste L en ordre croissant.
Considérons la liste L contenant les 7 éléments suivants :
L 14 2 47 10 18 13 5
0 1 2 3 4 5 6
Soit une variable booléenne Echange qu’on initialise à faux et qui revient vrai à chaque fois que
nous réalisons une permutation. Faux

Passage 1 Echange
- On compare 14 et 2. Puisque 14>2, on permute 14 et 2 et on met vrai dans la variable
Echange.
Vrai
L 2 14 47 10 18 13 5
0 1 2 3 4 5 6
Echange
- On compare 14 et 47. Puisque 14<47, on ne fait rien.
Vrai
L 2 14 47 10 18 13 5
0 1 2 3 4 5 6 Echange

- On compare 47 et 10. Puisque 47>10, on permute 47 et 10 et on met vrai dans la


variable Echange.
Vrai
L 2 14 10 47 18 13 5
0 1 2 3 4 5 6 Echange
- On compare 47 et 18. Puisque 47>18, on permute 47 et 18 et on met vrai dans la
variable Echange.

L 2 14 10 18 47 13 5 Vrai
0 1 2 3 4 5 6
Echange
- On compare 47 et 13. Puisque 47>13, on permute 47 et 13 et on met vrai dans la
variable Echange.
Vrai
L 2 14 10 18 13 47 5
0 1 2 3 4 5 6 Echange
- On compare 47 et 5. Puisque 47>5, on permute 47 et 5 et on met vrai dans la variable
Echange.
Vrai
L 2 14 10 18 13 5 47
0 1 2 3 4 5 6 Echange
Puisqu’on a atteint la fin de la liste et la variable Echange a comme valeur vrai alors on recommence un
nouveau passage jusqu'à ce qu’on fasse un passage complet de liste sans effectuer aucune permutation.
N.B :
Dans le passage numéro 2 on travaille sur n-1 éléments
Dans le passage numéro 3 on travaille sur n-2 éléments
………..

 Code en python : ordre croissant


7
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

def tri_bulle(L) :
Echange = True
passage = 0
while Echange == True :
Echange = False
passage = passage + 1
for i in range(0,len(L)-passage):
if L[i] > L[i + 1]:
Echange = True
# On echange les deux elements
L[i],L[i+1] = L[i+1],L[i]
return(L)

3.3. Tri par insertion


 Principe :
Le tri par insertion consiste à chercher la position du ième élément dans la partie de la liste
commençant de 1 à i sachant que les i-1 premiers éléments sont triés. Si cette position est i,
l'élément est donc à sa bonne place, sinon, supposons que cette position est j. Ce j est forcément
entre 1 et i-1. On décale d'un pas vers l'avant (à droite) tous les éléments de j à i-1 puis on insère
l'élément d'indice i à la position j. On commence ce procédé à partir du 2ème élément i=2.
Cette méthode ressemble étroitement au rangement d'une main de cartes par un joueur de belotte.
 Exemple :
On se propose d’utiliser la méthode de tri par insertion pour trier une liste L en ordre croissant.
Considérons la liste L contenant les 7 éléments suivants :

L 2 14 4 3 18 13 5
0 1 2 3 4 5 6
On commence par le deuxième élément puisque si la liste contient un seul élément, il est considéré comme
trié.
Etape 1
- On compare L[1] avec L[0] avec le souci de la garder triée.
- Puisque L[1]>L[0], donc les deux premiers éléments sont déjà en ordre.

L 2 14 4 3 18 13 5
0 1 2 3 4 5 6
On passe à l’étape 2
Etape 2
- On compare L[2] avec L[1] avec le souci de la garder triée.
- Puisque L[2]<L[1], donc on permute L[2] par L[1]

L 2 4 14 3 18 13 5
0 1 2 3 4 5 6
- On compare L[1] avec L[0] avec le souci de la garder triée.
- Puisque L[1]>L[0], donc les deux premiers éléments sont déjà en ordre.

L 2 4 14 3 18 13 5
0 1 2 3 4 5 6
On passe à l’étape 3
Etape 3
- On compare L[3] avec L[2] avec le souci de la garder triée.

8
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

- Puisque L[3]<L[2], donc on permute L[3] par L[2]

L 2 4 3 14 18 13 5
0 1 2 3 4 5 6

- On compare L[2] avec L[1] avec le souci de la garder triée.


- Puisque L[2]<L[1], donc on permute L[2] par L[1]

L 2 3 4 14 18 13 5
0 1 2 3 4 5 6

- On compare L[1] avec L[0] avec le souci de la garder triée.


- Puisque L[1]>L[0], donc les deux premiers éléments sont déjà en ordre.

L 2 3 4 14 18 13 5
0 1 2 3 4 5 6
On passe à l’étape 4

et ainsi de suite jusqu'à avoir une liste triée…..
 Code en python : ordre croissant
def tri_insertion(L) :
for i in range(1, len(L)) :
j = i
while j > 0 and L[j] < L[j-1]:
L[j],L[j-1] = L[j-1],L[j]
j -= 1
return(L)

3.4. Tri par fusion


 Principe :
Le tri par fusion est un algorithme récursif basé sur le principe « diviser pour régner ». Son
processus consiste à diviser la liste de départ en deux sous-listes, trier les deux sous-listes puis
fusionner les sous-listes ainsi triées. La condition de terminaison de cet algorithme récursifest
d’avoir une liste à un seul élément.
 Exemple :
tri_fusion([6, 1, 2, 5, 4, 7, 3])
[6, 1, 2, 5] [4, 7, 3]
tri_fusion([6, 1, 2, 5])
[6, 1] [2,5]
tri_fusion([6, 1])
[6] [1]
tri_fusion([6])
-->[6]
tri_fusion([1])
-->[1]
‘’’fusion’’’ de [6] et [1] : [1, 6]
-->[1, 6]

tri_fusion([2, 5])
[2] [5]

9
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

tri_fusion([2])
-->[2]
tri_fusion([5])
-->[5]
‘’’fusion’’’ de [2] et [5] : [2, 5]
-->[2, 5]
‘’’fusion’’’ de [1, 6] et [2, 5] : [1, 2, 5, 6]
-->[1, 2, 5, 6]
tri_fusion([4, 7, 3])
[4] [7, 3]
tri_fusion([4])
-->[4]
tri_fusion([7, 3])
[7] [3]
tri_fusion([7])
-->[7]
tri_fusion([3])
-->[3]
‘’’fusion’’’ de [7] et [3] : [3, 7]
-->[3, 7]
‘’’fusion’’’ de [4] et [3, 7] : [3, 4, 7]
-->[3, 4, 7]
‘’’fusion’’’ de [1, 2, 5, 6] et [3, 4, 7] : [1, 2, 3, 4, 5, 6, 7]
-->[1, 2, 3, 4, 5, 6, 7]
 Code en python : ordre croissant
def fusion(L1, L2) :
if L1 == [ ] : return L2
if L2 == [ ] : return L1
if L1[0] < L2[0] :
return [L1[0]] + fusion(L1[1:], L2)
else :
return [L2[0]] + fusion(L1, L2[1:])
Tfusion(n) = O(n)
def tri_fusion(L) :
if len(L) <= 1 : return L
L1 = [L[x] for x in range(len(L)//2)]
L2 = [L[x] for x in range(len(L)//2, len(L))]
return fusion(tri_fusion(L1),tri_fusion(L2))
T(n) = 2 T(n/2) + Tfusion(n)

 Calcul de la complexité :
L’algorithme tri_fusion est de type « diviser pour régner ». Alors l’étude de sa complexité se
base sur ses trois phases:
Diviser : cette étape consiste au calcul du milieu de l’intervalle [d,f], sa complexité est en O(1).
Régner : l’algorithme résout récursivement deux sous-problèmes de tailles (n/2), d’où une
complexité en 2*T(n/2).
Combiner : la complexité de l’algorithme de fusion qui est de O(n) pour la construction d’une
liste solution de taille n.
T(n) = 2 T(n/2) + O(n)

10
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

 a = 2, b = 2, k = 1 (2ème cas)
 O(T(n)) = O(n log2n)

3.5. Tri rapide (ou quicksort)


 Principe :
Le tri rapide est un algorithme récursif. Le processus de cet algorithme est basé sur la
recherche d’un élément particulier, appelé pivot, puis de placer tout les éléments plus petits que lui
à sa gauche, et tout les éléments strictement plus grands à sa droite. Le pivot est à son placement
définitive et l’opération se répète sur les sous-listes gauche et droit jusqu’à arriver à des listes à
trier. Le choix du pivot peut être fait au hasard. On fera le tri en place.
 Exemple :
Tri rapide à la main de [7, 3, 6, 4, 2, 5, 1]
- Appel sur L = [7, 3, 6, 4, 2, 5, 1]
pivot = 4, L1 =[3, 2, 1], L2 = [7, 6, 5]
- Appel récursif sur L1 = [3, 2, 1]
pivot = 2, L11 =[1], L12 = [3]
L1 devient : L11 + [2] + L12 = [1, 2, 3]
- Appel récursif sur L2 = [7, 6, 5]
pivot = 6, L21 =[5], L22 = [7]
L2 devient : L21 + [6] + L22 = [5, 6, 7]
L devient : L1 + [4] + L2 = [1, 2, 3, 4, 5, 6, 7]

 Code en python : ordre croissant


import random
def tri_rapide(list) :
inferieur = [ ] ; pivot = [ ] ; superieur = [ ]
if len(list) < 2:
return list
pivotNombre = random.choice(list)
for i in list:
if i < pivotNombre:
inferieur.append(i)
elif i > pivotNombre:
superieur.append(i)
else:
pivot.append(i)
return tri_rapide(inferieur) + pivot + tri_rapide(superieur)
 Calcul de la complexité :
 Pire cas

11
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Le cas pire intervient quand le partitionnement produit une région à n-1 éléments et une à 1
élément.
Vu que la complexité du partitionnement est de l’ordre de O(n) et que T(1) = O(1), la
récurrence pour le temps d’exécution est : T(n) = T(n-1) +O(n)
et on obtient : T(n) = O(n²)
 Meilleur cas :
Le meilleur cas est quand le partitionnement produit deux parties de longueur (n/2.)
La récurrence est alors définie par : T(n) = 2 T(n / 2) + O(n)
ce qui donne d’après le théorème de résolution des récurrences : T(n) = O(n log(n))

Bibliographie :
1. https://openclassrooms.com/courses/un-peu-de-recherche-ne-peut-faire-que-du-bien
2. https://fr.scribd.com/doc/291545781/Cours-Python-pdf
3. https://fr.scribd.com/document/70358138/Tut-Oriel-Python
4. http://shuxue.free.fr/Acces_cours/IPT/IPT_cours_complexite_2015_2016_PCSI.pdf
5. https://fr.scribd.com/document/268947032/Algorithme-et-Programmation
6. http://apcpedagogie.com/cours-et-tutoriels/les_cours/cours-de-
programmation/algorithme/algorithme-de-tri/
7. http://slideplayer.fr/slide/482390/
8. http://wwwdi.supelec.fr/liesse/html/exercices_td1.html
9. https://fr.wikipedia.org/wiki/Tri_fusion

12
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

CHAPITRE VII:
Manipulation des fichiers
Python

1. Introduction
Jusqu'à présent, nous n'avons travaillé que sur des données rentrées par l'utilisateur (input).
Evidemment, un programme doit être capable d'aller chercher des informations dans un
fichier (fichier texte par exemple) et écrire des résultats dans un (autre) fichier.
Python propose un objet Fichier < file > et un ensemble de méthodes pour lire et écrire
depuis/dans un fichier.

2. Utilité des fichiers


Lors de la fermeture de votre programme, aucune de vos variables n’est sauvegardée, or les
fichiers peuvent être, justement, un excellent moyen d’enregistrer des données pour pouvoir
les récupérer quand vous rouvrirez votre programme.

3. Noms de fichiers/répertoire courant


Avec Python, le répertoire courant est le répertoire (dossier) où se trouve le script que vous
êtes entrain de programmer, sauf si ce script est lancé depuis la fenêtre d’un shell IDLE,
auquel cas le répertoire courant est déterminé au lancement de IDLE lui-même (avec
Windows, ce répertoire est définie dans les propriétés de l’icône de lancement).
De préférence, les noms de fichiers sont choisis courts. Il vaut mieux, vous évitez les
caractères accentués, les signes typographiques spéciaux et les espaces.
 Le module OS
Ce module permet essentiellement la manipulation des fichiers (et des répertoires) c’est-
à-dire parcourir, renommer, création/destruction de répertoire. Le tableau suivant contient
quelques fonctions utiles.
getcwd() Fournit le répertoire courant
chdir(nomrep) Se place dans le répertoire nomrep
rename(src,dest) Renomme src en dest
remove(chemin) Supprime chemin
rmdir(chemin)
mkdir(chemin) Crée le répertoire chemin
listdir(chemin) Liste des fichiers/rep de chemin
 Le module os.path
split(chemin) Fournit le tuple(répertoire, fichier)
join(chemin,…) Fournit un nom complet:/plus/de/un/rep/un Fichier
exists(chemin) Vrai si chemin existe
isfile(chemin) Vrai si chemin est un fichier
isdir(chemin) Vrai si chemin est un répertoire

 Le module shutil
Ce module fournit des fonctions de copie.
copy(src,dest) Copie complète du fichier(y compris les droits)
copyfile(src,dest) Copie complète du fichier sans les droits

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

4. Ouverture et fermeture d’un fichier


 Ouverture d’un fichier
Pour pouvoir lire un fichier, il faut tout d’abord commencer par son ouverture par la
fonction open.
Open prend le chemin du fichier en paramètre, ainsi qu'un indicateur du mode de
lecture/écriture, et renvoie un fichier que l'on pourra lire.
fichier = open("chemin_fichier", "mode")
L’objet fichier est maintenant une variable sur lequel on pourra appliquer des méthodes
permettant de lire et/ou écrire dans ce fichier.
Remarque : Le chemin du fichier "chemin_fichier" peut être soit relatif ou absolu.
 Un chemin relatif est un chemin qui tient en compte l'emplacement de lecture.
 Un chemin absolu est un chemin complet qui peut être parcouru quelque soit
l'emplacement de lecture.
Plusieurs modes d’ouverture de fichiers existent :
 r: pour une ouverture en lecture (READ).
 w: pour une ouverture en écriture (WRITE), le contenu du fichier est écrasé à chaque
ouverture. Si le fichier n'existe pas Python le génère.
 a: pour une ouverture en mode ajout à la fin du fichier (APPEND). Si le fichier n'exist
e pas Python le génère.
 t : pour une ouverture en mode texte.
 b : pour une ouverture en mode binaire.
Exemple :
try:
fich=open("test.txt","r")
# opérations sur le fichier…..
fich.close()
except :
print("fichier introuvable")
Si le fichier n’existe pas la clause except sera déclenchée pour préciser le non existence du fic
hier.

 Fermeture d’un fichier


Une fois utilisé, on ferme le fichier en appelant la méthode close de ce fichier.
fichier.close()

5. Création et écriture dans un fichier


Pour écrire dans un fichier, il faut l'ouvrir en mode écriture avec l'un de ces indicateurs :
 w : pour (re)écrire un fichier en partant de zéro (w comme write)
 a : pour écrire à la suite d'un fichier existant (a comme append)
C’est la méthode write qui permet d‘écrire dans le fichier si le fichier n’existe pas elle le
créera. L'argument de la méthode write() doit être une chaîne de caractères.

2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Exemple:
fich=open("test.txt","w")
# opérations sur le fichier….
fich.close()

 Fichier texte
fich=open("test.txt","w")
fich.write("Salut ceci \n est mon premier fichier texte créé
depuis Python!!!!")
fich.close()

6. Lecture d’un fichier


Pour afficher tout le contenu d'un fichier, vous pouvez utiliser la méthode read sur l'objet-
fichier.
Exemple de read:
f=open("test.txt","r")
ch=f.read()
print(ch, type(ch))
ch.close()
La méthode read lit le contenu de tout le fichier dans une chaine de la même manière avec
laquelle le texte a été enregistré dans le fichier.
Nous pouvons lire un nombre précis de caractères : ch=f.read(5) lit les 5 premiers caractères.
Deux autres méthodes existent pour la lecture readline (lecture d’une seule ligne, celle en
cours) et readlines retournant une liste contenant toutes les lignes du fichier texte.
Remarque : La lecture dans un fichier est une lecture séquentielle.
Exemple de readline:
#lecture d’une ligne
f=open("test.txt","r")
Ligne_cour=f.readline()
print(Ligne_cour, type(Ligne_cour))
>>>Salut
<class 'str'>
Exemple de readlines:
f=open("test.txt","r")
L=f.readlines()
print(L, type(L))
>>>
['Salut \n', 'ceci est mon premier fichier texte\n', 'créé depuis
Python!!!'] <class 'list'>

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Deux méthodes sont utiles pour l’extraction des données strip() et split()
 strip():enlève le caractère de saut de ligne
 split():retourne une liste contenant les chaines séparés selon les espace sinon préciser
le séparateur
Exemple :
>>> ch="kj, kj kj , kjkjk kjk , kjkj\n"
>>> ch.strip()
…………………………………………………………………………………………………………………………………………
>>> ch.strip().split()
…………………………………………………………………………………………………………………………………………
>>> ch.strip().split(',')
……………………………………………………………………………………………………………………………………….

7. Enregistrement et restitution de variables diverses


Comme nous avons vu dans les sections précédentes, l’argument de la méthode write()
pour un fichier texte est de type chaîne de caractères (str). Si on a d’autres types, il faut les
transformant d’abord en chaînes de caractères à l’aide de la fonction intégrée str().
>>>x=52
>>>f.write(str(x))
Nous verrons plus loin qu’il existe d’autres possibilités pour convertir des valeurs
numériques enchaînes de caractères). Mais la question n’est pas vraiment là. Si nous
enregistrons les valeurs numériques en les transformant d’abord en chaînes de caractères,
nous risquons de ne plus pouvoir les retransformer correctement en valeurs numériques lors
de la lecture du fichier.
Exemple:

Dans cet exemple, trois valeurs numériques sont enregistrées. Comme vous avez remarqué,
on ne peut pas les distinguer dans la chaîne de caractères résultante lors la lecture du fichier.
Il existe plusieurs solutions pour ce type de problèmes. L’une des meilleures est d’importer
un le module pickle.
Voici comment il s’utilise:

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Nous pouvons remarquer dans cet exemple que le module pickle permet d’enregistrer des
données en gardant leur type. Les contenus des trois variables a, b et c sont sauvegardés dans
le fichier donnees_test, et ensuite régulièrement restitués, avec leur type, dans les variables j,
k et l. Vous pouvez donc mémoriser importe quel type de données.

Attention: les fichiers traités à l’aide des fonctions du module pickle sont des fichiers
binaires. Pour cette raison, ils doivent obligatoirement êt re ouverts comme tels à l’aide de la
fonction open(). Vous utiliserez l’argument 'wb' pour ouvrir un fichier binaire en écriture
(comme à la 3eme ligne de notre exemple), et l’argument 'rb' pour ouvrir un fichier binaire
en lecture (comme à la 8eme ligne de notre exemple).
La fonction dump() du module pickle a deux arguments: le premier est la variable à
enregistrer, le second est l’objet fichier concerné. La fonction pickle.load() effectue le travail
inverse, c’est-à-dire la restitution de chaque variable avec son type.

Bibliographie :
1. https://python.developpez.com/cours/TutoSwinnen/?page=Chapitre9
2. Samia Darragi, Cours Python, IPEST, 2014-2015
3. https://openclassrooms.com/courses/apprenez-a-programmer-en-python/les-fichiers-2

5
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

CHAPITRE VIII:

Système de numération

1. Introduction
Dans une machine, toutes les informations sont codées sous forme d’une suite de ‘‘0’’ et
de ‘‘1’’ (langage binaire). Les programmeurs ne préfèrent pas l’implémentation en langage
binaire car elle n’est pas assez facile. Il faut donc avoir une étape de traduction pour que
l’ordinateur puisse exécuter les instructions correspondantes aux informations qu’on peut lui
donner. Cette traduction est une opération de codage établissant une bijection entre une
information et une suite de ‘0’ et de ‘1’ qui sont représentables en machine.
Le but de ce chapitre est donc, de :
- Connaître la notation binaire des nombres (entiers et réels) et les opérations
élémentaires effectuées sur ces nombre en binaire
- Savoir la représentation d’un nombre dans une base B (2, 8, 10, 16, …)
- Connaître les limites de la représentation : erreurs d’arrondi et de débordement de la
mémoire.

2. Codage des nombres entiers


Nous avons l’habitude d’écrire nos nombres et de faire des calcules dans le système
décimal. Il s’agit en fait d’un cas particulier de numération à base 10. Il existe d’autres
systèmes de numération autre que le système décimal qu’on va détailler.

2.1. Les systèmes de numération


Un système de numération permet d’associer à chaque nombre une suite de symbole. Ce
système utilise un nombre limité de symbole. Le nombre de symboles forme la base du
système. Un nombre est représenté dans une base B disposant de B symboles (0 à B-1).
Soit N = (an-1…a1a0)B :
 En décimal, B = 10, ai  0 ; 1; 2; 3; 4; 5; 6; 7; 8; 9 :10 chiffres ;
 En binaire, B = 2, ai  0; 1 : 2 chiffres binaires, ou bits ;

n n-1 n-2 … 4 3 2 1 0
Les cases du schéma représentent les bits, le chiffre marqué en dessous d’une case
indique la puissance de 2 à laquelle est associé ce bit (ou le rang du bit). Le bit de rang
0 consiste au bit de poids faible. Le bit de rang n consiste au bit de poids fort.
 En octal, B=8, ai  0; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 :8 chiffres ;
 En hexadécimal, B = 16, ai  0; 1; 2; 3; 4; 5; 6; 7; 8; 9; A; B; C; D; E; F (on utilise
les 6 premières lettres comme des chiffres) :16 chiffres.
N.B. C’est un système très souvent utilisé en informatique.

1
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

2.2. Transcodage : Passage d’une base à une autre


 Décimal (10) B (2, 8, 16) :
Soit un nombre N écrit dans la base 10, la conversion s’effectue avec 2 méthodes :
1ère méthode : diviser le nombre par la base B, ensuite le quotient trouvé par la base B et ainsi
de suite jusqu’à l’obtention d’un quotient nul. Les restes successifs de bas en haut constituent
la représentation du nombre dans la base B (an-1…a1a0).
N B
R1 Q1 B
R2 Q2 B N 10 =RnRn-1……..R1 B
R3 Q3
R4
Qn- B
1
Rn Qn=0

2ème méthode : soustraire successivement la plus grande puissance de B.


N 10 = an-1*Bn-1+ …… a2*B2+ a1*21+a0*20  N 10 =an-1……. a1 a0 B

Exercice:
1) Donnez les représentations binaires des nombres entiers suivants : 4 10,7 10, 25 10

1ère méthode 2ème méthode

2
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

2) Donnez les représentations octales des nombres entiers suivants :15 10, 2410, 6510

1ère méthode 2ème méthode

3) Donnez les représentations hexadécimaux des nombres entiers suivants : 2710, 3110,
25610

1ère méthode 2ème méthode

 B (2, 8, 16)  Décimal :


Soit N un nombre représenter en une base B, la conversion en décimale se fait en appliquant
l’écriture polynomiale comme suit :
N = (an-1…a1a0)B
N’10 = 𝑛 −1
𝑖=0 𝑎𝑖 𝐵
𝑖
= an-1*Bn-1+ …… a2*B2+ a1*B1+a0*B0

3
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exercices:
1) Donnez les représentations décimales des nombres binaires : 1001012, 10112 :
1001012 =……………………………………………………………………………………...

10112 =………………………………………………………..………………………………

2) Donnez les représentations décimales des nombres octaux: 518, 158 :


518=………………………………….…………………………………………………………

15 8=…………………...………………………………………………………………………..

3) Donnez les représentations décimales des nombres hexadécimaux : 2A16, D5416, 1B16:
2A16=…………………………………………………………………………………………….

D5416=…………………………………………………………………..……………………….

1B16 =……………………………………………………………………………………………

 Binaire (2)  B = 2n (8 et 16):


Le passage de la base binaire à une base B se fait en se décomposant le nombre binaire en des
tranches de taille n que l’on convertit en B.
Exemples :
1) soit le nombre binaire 1 010 011 1012
La conversion en octal se fait comme suit :
0 0 1 0 1 0 0 1 1 1 0 1
1 2 3 5

001 010 011 101 2 = 1 2 3 5 8


2) soit le nombre binaire 10 1111 1010 10112
A B C D E F
10 11 12 13 14 15

La conversion en hexadécimal se fait comme suit :


0 0 1 0 1 1 1 1 1 0 1 0 1 0 1 1
2 15 10 11
2 F A B

10 1111 1010 10112=2FAB16

Exercice:
Convertissez les nombres binaires suivants :
 1101111102 en nombre octal,
 100001102 en nombre hexadécimal.

110111110 2=…………………………………………………………………………………

10000110 2=………………………………………………………………………………….

4
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

 B = 2n(8 et 16)  Binaire (2):


Le passage d’une base B à la base binaire s’effectue en convertissant chaque chiffre en base 2
et en juxtaposant les résultats.

Exemples :
1) soit le nombre octal 6412 8 8 = 23
6 4 1 2
1 1 0 1 0 0 0 0 1 0 1 0
6412 8=110100001010 2

2) soit le nombre Hexadécimale 69FB 16 16 = 24


6 9
F B
6 9
15 11
0 1 1 0 1 0 0 1 1 1 1 1 1 0 1 1
69FB 16=01101001111110112

Exercices:
1) Convertissez les nombres octaux suivants en nombres binaires : 1138, 108, 53628.

113 8=…………………………………………………………………………………………..

10 8=…………………………………………………………………………………………

2) Convertissez les nombres hexadécimaux suivants en nombres binaires : 9AB16, 96916.


9AB 16=……………………………………………………………………………………..

969 16=………………………………………………………………………………………

2.3. Conversion entre hexadécimal et octal


Pour faire la conversion entre l’hexadécimal et l’octal on doit passer par une base
intermédiaire.

Base 10

Base 16 Base 8

Base 2

5
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exercice :

1) Convertissez les nombres hexadécimaux suivants en nombres octaux :

1FC 16= ………………..8


101023 16= ……………….8
2) Convertissez les nombres octaux suivants en nombres hexadécimaux :

752 8= ……………….16
110110 8= ……………….16

3. Opérations arithmétiques binaires


3.1. Addition binaire
Ce paragraphe présente la structure de base permettant de réaliser l'addition entre deux
nombre binaires de n bits.

Additionneur binaire

La table d'addition binaire sur 2 bits est la suivante:


a b s r
0 + 0 = 0 0
0 + 1 = 1 0
1 + 0 = 1 0
1 + 1 = 0 1
L'opération d'addition de deux représentation binaires s'effectue de façon similaire à l'addition
décimale c'est à dire en additionnant digit par digit les deux représentations alignées et en
reportant une éventuelle retenue sur la colonne suivante.
L'addition est une opération associative, on peut aisément déduire la table d'addition binaire
sur 3 bits de la table d'addition binaire sur 2 bits :
Soit deux nombres A (A= an-1 ... a0) et B (B= bn-1 ... b0).
a b r s r1
0 0 0 = 0 0
0 0 1 = 1 0
0 1 0 = 1 0
0 1 1 = 0 1
1 0 0 = 1 0
1 0 1 = 0 1
1 1 0 = 0 1
1 1 1 = 1 1

6
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exemple (Addition)
 Addition binaire (8 bits) :

 Addition binaire (8 bits) avec (débordement ou overflow) :

3.2. La multiplication binaire


Le processus de multiplication binaire est en fait beaucoup plus simple que le processus
de multiplication décimale dans la mesure les tables de multiplications des chiffres se limitent
au ET logique. La table de multiplication binaire est la suivante :
a b s
0 * 0 = 0
0 * 1 = 0
1 * 0 = 0
1 * 1 = 1
Pour chaque digit du multiplieur égal à 1, un produit partiel non nul est formé. Ce produit est
constitué du multiplicande décalé d'un certain nombre de positions de manière à aligner son
digit de poids le plus faible avec le 1 correspondant du multiplieur. Le produit final est obtenu
par addition de tous les produits partiels.
Le processus de multiplication binaire est expliqué par l'exemple suivant:

3.3. La soustraction binaire


Ce paragraphe présente la structure de base permettant de réaliser la soustraction entre
deux nombre binaires de n bits.

7
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Soustracteur binaire
La table de soustraction sur 2 bits est la suivante:
a b s r
0 - 0 = 0 0
0 - 1 = 1 1
1 - 0 = 1 0
1 - 1 = 0 0
Les relations donnant la somme et la retenue sur trois bits sont les suivantes :
Soit deux nombres A (A= an-1 ... a0) et B (B= bn-1 ... b0) et soit à réaliser l'opération A-B.
a b r s r1
0 0 0 = 0 0
0 0 1 = 1 1
0 1 0 = 1 1
0 1 1 = 0 1
1 0 0 = 1 0
1 0 1 = 0 0
1 1 0 = 0 0
1 1 1 = 1 1
3.4. La division binaire
La division est la plus complexe des 4 opérations arithmétiques. Le principe de la
division décimale classique est fondé sur le principe d'essais successifs. Par exemple, pour
diviser 11 par 4, on doit d'abord s'apercevoir que 11 est supérieur à 4 et ce demander combien
de fois 4 va dans 11. Si l'on fait un essai initial avec 3, la multiplication 3*4=12 nous indique
que le choix est mauvais (12>11). Il faut recommencer avec 2 etc...
Compte tenu du moins grand nombre de possibilité d'essais, ce principe d'essais successifs et
en fait beaucoup plus simple dans la division binaire.
Exemple :
1011 100
- 10,11
100
-------
0011
-
000
----------
0110
-
100
----------
0100
-
100
-----------
0000
8
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

4. Représentation d'un nombre dans un ordinateur


La représentation (ou encore codification) d'un nombre est la manière selon laquelle il est
représenté sous forme binaire. La représentation des nombres sur une machine est obligatoire
pour qu’elle soit capable de les sauvegarder, les manipuler.

4.1. Représentation d'un entier naturel


La représentation d’un entier naturel demande tout d’abord la définition du nombre de bits
nécessaire pour son codage. Ensuite, il suffit de disposer chaque bit dans la cellule binaire
correspondant à son poids binaire de la droite vers la gauche, puis les bits non utilisés sont
remplis par des zéros.

4.2. Représentation d'un entier relatif


Un entier relatif est un entier naturel possédant un signe positif ou négatif. Il faut donc
tenir compte dans la représentation de son signe pour qu’on puisse savoir s'il s'agit d'un
nombre positif ou négatif. De plus, il faut que les règles d'addition soient maintenues. Alors il
existe un codage particulier appelé codage complément à deux dont son principe est comme
suit :
 Un entier relatif positif ou nul est représenté en binaire comme un entier naturel, avec
la différence que le bit de poids fort (le bit situé à l'extrême gauche) indique le signe
(0 : signe positif, 1 : signe négatif). Il faut donc se garantir que pour un entier positif que
ce bit est à zéro. Ainsi si on code un entier relatif sur cinq bits, le nombre le plus grand
sera 01111 (c'est-à-dire 15 en base décimale).
D'une manière générale le plus grand entier relatif positif codé sur n bits sera 2^ (n-1) -1.
 Un entier relatif négatif est représenté en suivant cette démarche:

On remarquera qu'en ajoutant le nombre et son complément à deux on obtient 0.


Exemple :
On désire coder la valeur -5 sur 8 bits. Il suffit :
D’écrire 5 en binaire : 00000101
De complémenter à 1 : 11111010
D'ajouter 1 : 11111011
La représentation binaire de -5 sur 8 bits est 11111011

Truc :

9
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

4.3. Représentation d’un réel


 Conversion de binaire en décimal :
Vous pouvez facilement convertir un nombre réel de la base 2 vers la base 10. Exemple :
110,1012 = 1*22 + 1*21 + 0*20 + 1*2-1 + 0*2-2 + 1*2-3 = 4 + 2 + 0,5 + 0,125 = 6,62510.

 Conversion de décimal en binaire :


Le passage de base 10 en base 2 est plus subtil.
Par exemple : convertissons 230,625 en base 2.
 La partie entière : on fait comme pour les entiers :

123410 = 27+26+25+22+21 =111001102


 La partie décimale : on multiplie par 2, puis on note la partie entière obtenue, on
recommence avec la partie décimale restante et on s’arrête quand la partie décimale est
nulle ou quand la précision souhaitée est atteinte. La partie décimale est la concaténation
des parties entières obtenues dans l’ordre de leur calcul :

0,625*2 = 1,25→0,625 = 0,1...


0,25*2 = 0,5 →0,625 = 0,10...
0,5*2 = 1,0 → 0,625 = 0,101
Donc 230,62510 = 11100110.1012
Remarque :
Si m est le nombre de chiffres après la virgule de l’écriture décimal et n est le nombre de
chiffres après la virgule du nombre dans la base B, alors :
𝒍𝒐𝒈(𝟏𝟎)
𝒏= 𝒎∗
𝒍𝒐𝒈(𝑩)
Exemple : B=2  n = 3,32 * m.

 Représentation d’un nombre réel :


Le codage d’un nombre réel se base sur la norme IEEE 754. Un nombre binaire à virgule sera
représenté sous la forme 1,XXXXX... * 2n.
En effet, cette norme se propose de coder les nombres selon deux types et définit trois
composants (Signe, Exposant et Mantisse) :
Type Signe Exposant Mantisse Total
Simple précision 1 bit 8 bits 23 bits 32 bits (4 octets)
Double précision 1 bit 11 bits 52 bits 64 bits (8 octets)
 Le signe est représenté par un seul bit, le bit de poids fort (celui le plus à gauche)
 L'exposant biaisé est codé sur les bits (8 ou 11) consécutifs au signe.

 La mantisse (les bits situés après la virgule) est codé sur les bits (23 ou 52) restants.

10
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Exemple 1:
Soit à coder la valeur 525,5 en simple précision:

Exemple 2:
Soit à coder la valeur -0,625 en simple précision :

5. Précision et erreurs d’arrondi


La représentation des nombres réels pose un problème c’est que les réels sont continus. En
effet, l’ordinateur ne travaille que sur un nombre limité de digits. Ce qui nécessite d’arrondir
les représentations et ceci entraine des erreurs d’arrondi.
L’ordinateur ne peut pas représenter les réels arbitrairement grands ou petits car ça cause des
problèmes de débordement.
Le plus souvent l’encodage se fait de manière approchée en donnant une précision voulue.

Bibliographie :
1. http://www.memoireonline.com/12/13/8266/m_Codage-et-transmission-des-donnees-dans-un-
reseau11.html
2. http://rmdiscala.developpez.com/cours/LesChapitres.html/Cours1/Chap1.3.htm
3. http://www.fsr.ac.ma/cours/informatique/elbenani/Codage.pdf
4. http://jacquesvladimir.blogspot.com/
5. http://www.commentcamarche.net/contents/100-representation-des-nombres-entiers-et-reels
6. http://docplayer.fr/12703130-Microprocesseurs-et-microcontroleurs.html

11
ISSAT Gabès AU : 2016/2017 Sections : MP1, PC1 & T1

Annexe

décimale Binaire Octale hexadécimale


0 0000 0 0
1 0001 1 1
2 0010 2 2
3 0011 3 3
4 0100 4 4
5 0101 5 5
6 0110 6 6
7 0111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
16 00010000 20 10
17 00010001 21 11
18 00010010 22 12
19 00010011 23 13
20 00010100 24 14
21 00010101 25 15
22 00010110 26 16
23 00010111 27 17
24 00011000 30 18
25 00011001 31 19
26 00011010 32 1A
27 00011011 33 1B
28 00011100 34 1C
29 00011101 35 1D
30 00011110 36 1E
31 00011111 37 1F
32 00100000 40 20
33 00100001 41 21
34 00100010 42 22
35 00100011 43 23
36 00100100 44 24
37 00100101 45 25
38 00100110 46 26
39 00100111 47 27
40 00101000 50 28

12
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

CHAPITRE IX:

Simulation numérique

I. Généralités
Python fournit plusieurs fonctions dans des modules spécialisées. Ce qui demande de ne pas
encombrer la mémoire de fonctions dont on ne se servira pas. On peut donc importer les modules
contenant les fonctions qu’on a besoin.
Pour se servir d’une fonction fct d’un module mod, il nécessite l’import de cette fonction, ou
tout le module avant son utilisation.
>>>import mod
>>>mod.fct
Certains noms de module sont longs, ou seront utilisés très souvent. On peut, au moment de
l’import du module, créer un alias, qui sera utilisé lors de l’appel des fonctions de ce module au
lieu du nom complet:
>>>import mod as al
>>>al.fonct
Dans ce chapitre, nous nous intéressons en particulier aux modules numpy, scipy (spécifiques
pour le calcul scientifique) et matplotlib (spécifique pour le dessin de courbe 2D/3D).

II. Module Numpy


Dans toute la suite on supposera qu’on a effectué : >>> import numpy as np

1. Manipuler des tableaux et des matrices


numpy propose un type numpy.ndarray qui fournit les fonctionnalités des tableaux de Python,
mais aussi des règles de calcul efficaces. Dans la suite nous appellerons « tableau numpy» toute
instance du type numpy.ndarray (ou plus simplement « tableau »).
Attention: contrairement aux listes, les éléments d’un tableau numpy sont tous être de même
type comme le cas des tableaux en algorithmique.

 Création de tableaux monodimensionnels


La fonction np.array transforme une liste Python en tableau numpy :
>>> u = [1, 4, 6, 2]
>>> type (u)
< class 'list'>
>>> t = np.array(u)
>>> t
array([1, 4, 6, 2])
>>> type (t)
<class 'numpy.ndarray'>

1
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

La fonction np.zeros crée un tableau composé uniquement de zéros de type float, le nombre
d’éléments étant passé en paramètre. Il est possible de modifier le type des éléments en utilisant
le paramètre facultatif dtype.
>>> np.zeros(6)
………………………………………………………………………………………………………………………………………………………………
>>> np.zeros(6, dtype = int)
………………………………………………………………………………………………………………………………………………………………
La fonction np.ones fonctionne comme np.zeros sauf que les éléments sont tous égaux à 1.
>>> np.ones(3, dtype = int)
………………………………………………………………………………………………………………………………………………………………
>>> 5 * np.ones(3)
………………………………………………………………………………………………………………………………………………………………
La fonction np.arange(d,f,pas) fonctionne comme range mais renvoie un objet de type
numpy.ndarray :
>>> x = np.arange(0, 1, 0.3)
>>> x
array([0., 0.3, 0.6, 0.9])
Les fonctions size, shape, len et ndim retournent respectivement le nombre d’éléments d’un
vecteur et la dimension.
>>> v=np.array([-1,3.,0,-2,5,8,0,22,0,-5])
>>> np.size(v)
10
>>> np.shape(v)
(10,)
>>> len(v)
10
>>> np.ndim(v)
1
 Création de tableaux bidimensionnels
La fonction np.array permet de transformer une liste de listes Python en tableau
bidimensionnel numpy :
>>> np.array([[1, 2], [3, 4]])
array([[1, 2],
[3, 4]])
Les fonctions np.zeros et np.ones fonctionnent comme dans le cas monodimensionnel, sauf le
paramètre sera un couple d’entiers formé par le nombre de lignes et le nombre de colonnes.
>>> np.zeros((2, 3))
…………………………………………………………………………………………………………………………………………………………………………
……………………………………………………………………………………………………………………………………………………………………..

La fonction np.eye renvoie la matrice identité (les coefficients de la diagonale principale sont
égaux à 1, les autres à 0) et elle a un seul paramètre entier, qui représente son ordre.
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
2
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

La fonction np.diag a comme paramètre une liste [t0, . . . , tn−1] (ou un tableau numpy) et
renvoie la matrice diagonale ayant les éléments ti sur la diagonale et des zéros ailleurs :
>>> np.diag([5, 7, 2])
array([[5, 0, 0],
[0, 7, 0],
[0, 0, 2]])
 Accès à un élément
L’accès à un élément ou une tranche d’éléments pour un tableau monodimensionnel se fait
comme pour les listes:
>>> v=np.array([-1,3.,0,-2,5,8,0,22,0,-5])
>>> v[0]
-1.0
>>> v[-1]
-5.0
>>> v[2:]
array([ 0., -2., 5., 8., 0., 22., 0., -5.])
>>> v[:3]
array([-1., 3., 0.])
>>> v[4:8]
array([ 5., 8., 0., 22.])
Accès à un élément pour un tableau bidimensionnel :
>>> m = np.array([[3, 8, 1],[2, 7, 3]])
>>> m[1] # ligne 1
array([2, 7, 3])
>>> m[1, 2] = 50 # ligne 1 colonne 2
>>> m
array([[3, 8, 1],
[2, 7, 50]])

 Opérateurs vectorialisés
Si vous travaillez avec des tableaux numpy, les opérations usuelles (+, −, *, /, **) se font
coefficient par coefficient.
>>> a = np.array([[1, 2] , [3, 4]])
>>> b = np.eye(2)
>>> a
array([[1, 2],
[3, 4]])
>>> b
array([[1., 0.],
[0., 1.]])
>>> a + b
array([[2., 2.],
[3., 5.]])
>>> a – b
array([[0., 2.],
[3., 3.]])
>>> a * b
array([[1., 0.],
[0., 4.]])

3
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Vous pouvez aussi ajouter (soustraire ou multiplier) une constante à un tableau numpy, dans
ce cas l’opération se fait coefficient par coefficient.
>>> 3 + a
array([[4, 5],
[6, 7]])
Attentions :
- L’opérateur + de numpy n’est pas du tout le même que celui des listes Python. Avec les
listes cet opérateur consiste à une concaténation, avec les tableaux numpy il s’agit d’une
addition terme à terme.
- Les opérateurs *, /, ** de numpy ne correspondent pas aux opérations matricielles
mathématiques. Ils effectuent simplement un produit (ou une division ou une mise à la
puissance) coefficient par coefficient.
 Slicing, vues, copies
Vous pouvez sélectionner une sous-matrice en ne conservant que certaines lignes
consécutives et/ou certaines colonnes consécutives.
Un intervalle d’indices est représenté comme suit :
 debut:fin:pas : les indices entre debut inclus et fin exclu, séparés par la valeur pas;
 debut:fin : tous les indices entre debut inclus et fin exclu) ;
 debut: : tous les indices depuis debut inclus ;
 :fin : tous les indices jusqu’à fin exclu;
 : : tous les indices;
 i : seulement l’indice i.
La syntaxe matrice[intervalle d'indices de lignes, intervalle d'indices de colonnes] permet de
créer une sous-matrice correspondant aux lignes et aux colonnes sélectionnées.
>>> m = np.array([[1, 2, 5, 3], [4, 7, 2, 4], [3, 1, 2, 6]])
>>> m
array([[1, 2, 5, 3],
[4, 7, 2, 4],
[3, 1, 2, 6]])
>>> m[ : : 2, : ] # lignes d’indices pairs
array([[1, 2, 5, 3],
[3, 1, 2, 6]])
>>> m[1 : , 1 : 3] # lignes 1 et suivantes, colonnes 1 et 2
array([[7, 2],
[1, 2]])
>>> m[ : , 2] # colonne 2
array([5,2,2])
Une sous-matrice ainsi obtenue s’appelle une vue. Les coefficients ne sont pas recopiés.
>>> a = m[1 : , 1 :]
>>> a
array([[7, 2, 4],
[1, 2, 6]])
>>> a[0, 0] = 20
>>> m
array([[1, 2, 5, 3],
[4, 20, 2, 4]
[3, 1, 2, 6]])

4
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Si on veut une duplication des éléments d’une matrice numpy, on utilise la fonction np.copy :
>>> a = np.copy(m[1 : , 1 :])
>>> a[0, 0] = 20
>>> m
array([[1, 2, 5, 3],
[4, 7, 2, 4]
[3, 1, 2, 6]])
 shape, reshape, concatenate
L’attribut shape est un n-uplet où n est le nombre d’entrées du tableau numpy. Dans le cas
monodimensionnel, l’attribut shape est un 1-uplet contenant le nombre d’éléments. Dans le cas
bidimensionnel, l’attribut shape est un couple (nombre de lignes, nombre de colonnes).
La méthode reshape permet de reconstituer un tableau numpy et de retourner un nouveau
tableau, dont la géométrie est un uplet passé en paramètre.
La méthode concatenate du module numpy permet d’assembler les vecteurs et les matrices
et de les concaténer. Par défaut l’assemblage se fait selon la 1 ère dimension (les lignes, donc
assemblage vertical).
>>> vecteur = np.array([1, 5, 2, 7, 3, 8])
>>> vecteur.shape
(6, )
>>> matrice = np.concatenate((vecteur, vecteur+1, 2*vecteur))
>>> matrice
array([1, 5, 2, 7, 3, 8, 2, 6, 3, 8, 4, 9, 2, 10, 4, 14, 6, 16])
>>> matrice.shape
(18, )
>>> p = matrice.reshape(2, 9)
>>> p
array([[ 1, 5, 2, 7, 3, 8, 2, 6, 3],
[ 8, 4, 9, 2, 10, 4, 14, 6, 16]])
>>> p.shape
(2, 9)

2. Quelques outils d’algèbre linéaire


Syntaxe Exemple
>>>import numpy as np
Produit numpy.dot(matrice A, matrice B) >>>np.dot([[1,2],[3,4]], np.eye(2))
matriciel Valeur de retour : le produit array([[1. , 2.],
matriciel A . B [3. , 4.]])

>>>a=np.arange(15).reshape(3,5)
>>>a
numpy.rank(matrice A) array([[ 0, 1, 2, 3, 4],
Rang d’une [ 5, 6, 7, 8, 9],
Valeur de retour : le rang de la
matrice matrice A [10, 11, 12, 13, 14]])
>>>np.rank(a)
2
numpy.linalg.inv(matrice A) >>>from numpy.linalg import inv
Inverse Valeur de retour : A-1 (provoque >>>inv([[1,2],[3,4]])
d’une une erreur si A n’est pas array([[-2. , 1. ],
matrice inversible) [ 1.5, -0.5]])

5
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Syntaxe Exemple
numpy.linalg.det(matrice A) >>>from numpy.linalg import det
Déterminant Valeur de retour : le déterminant >>>det([[1,2],[3,4]])
de A, de type float -2.0000000000000004
numpy.trace(matrice A) >>> np.trace([[1,2],[3,4]])
Trace 5
Valeur de retour : la trace de A
résolution de x +2y = 2
numpy.linalg.solve(matrice A,
Résolution 3x +4y = 8
vecteur B)
d’un système Valeur de retour : le vecteur X
>>>from numpy.linalg import solve
de Cramer >>>solve([[1,2],[3,4]],[2,8])
solution de AX = B array([ 4., -1.])
>>>from numpy.linalg import
Puissance numpy.linalg.matrix_power(matri matrix_power
d’une ce A, entier n) >>>matrix_power([[1,2],[3,4]], -2)
matrice Valeur de retour : An array([[ 5.5 , -2.5 ],
[-3.75, 1.75]])
>>> np.transpose([[1,2],[3,4]])
array([[1, 3],
[2, 4]])
Transposée
numpy.transpose(matrice A) Autre possibilité :
d’une Valeur de retour : t A >>> A = np.array([[1,2],[3,4]])
matrice >>> A.T
array([[1, 3],
[2, 4]])
>>>from numpy.linalg import eigvals
les valeurs >>> eigvals(A)
numpy.linalg.eigvals (matrice A)
propres array([-0.37228132, 5.37228132])
>>>from numpy.linalg import eig
>>> eig(A)
les vecteurs (array([-0.37228132, 5.37228132]),
numpy.linalg.eig(matrice A)
propres array([[-0.82456484, -0.41597356],
[ 0.56576746,-0.90937671]]))

III. Module matplotlib (tracé de courbes)


Le module matplotlib est un module Python réservé pour le traçage et la visualisation des
données sous formes de graphiques.
Nous utiliserons plus souvent le sous-module matplotlib.pyplot, que nous supposerons importé
sous l’alias plt. Voici les principales fonctions : destiner

Fonction Rôle
Trace la ligne brisée entre les points dont les abscisses sont dans la
plt.plot(X,Y, label='nom') liste X et les ordonnées dans la liste Y. Le label sert à identifier la
courbe
plt.title("titre") Définit le titre du graphe (affiché en haut)
plt.grid( ) Affiche une grille en pointillés pour une meilleure lisibilité
Affiche une légende en associant à chaque courbe son label.
plt.legend(loc= ...) L’option loc précise l’emplacement de légende, qui peut être un
nombre (1,2, ..) ou un texte ('upper left')
plt.savefigure('nom.ext') Sauvegarde le graphe dans un fichier de ce nom. L'extension
définit le format. Voir l'aide pour savoir les formats acceptés
plt.show( ) Affichage à l'écran de la figure

6
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 Tracés de lignes brisées et options de tracés


La fonction plot permet de tracer une ligne brisée en donnant la liste des abscisses et la liste
des ordonnées. La fonction axis permet de déterminer la fenêtre dans laquelle est contenu le
graphique.

import matplotlib.pyplot as plt


x = [1. , 2.5 , 4.]
y = [3. , 1., 5.]
plt. plot(x, y)
plt. axis ([ -1. , 5., -1., 6.])
plt. grid ( )
plt. show ( )

La fonction plot admet de nombreuses options de présentation. L’option color permet de


choisir la couleur ('g' : vert, 'r' : rouge, 'b' : bleu). L’option linestyle permet de définir le style de
la ligne ('-' : ligne continue, '--' : ligne discontinue, ':' : ligne pointillée). L’option marker permet
de marquer les points des listes ('+', '.', 'o', 'v', …).

import matplotlib.pyplot as plt


x = [1. , 2.5 , 4.]
y = [3. , 1., 5.]
plt.axis([ -1. , 5., -1., 6.])
plt.plot(x,y,color ='r',linestyle
=':', marker ='o')
plt.show()

 Tracés de fonction
Le traçage d’une courbe représentative d’une fonction consiste à définir une liste d’abscisses
puis de construire la liste des ordonnées correspondantes.
L’exemple ci-dessous trace la courbe de x →sin(x) sur [0, 3π].
import math
import numpy as np
import matplotlib.pyplot as plt

def f(x):
return math. sin(x)
X = np. arange (0, 3*
math.pi,0.01)
Y = [ f(x) for x in X ]
plt.plot(X, Y)
plt.show ()

7
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 Représentation 3D avec matplotlib


Pour créer un axes 3D, nous avons besoin de passer la projection d'argument = '3d'. Et définir
aussi 3 entrées x, y et z.
Exemple 1 :
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
ax=plt.axes(projection='3d')
z=np.linspace(0,1,100)
x=z*np.sin(20*z)
y=z*np.cos(20*z)
ax.scatter(x,y,z) #nuages de points
plt.show()

Exemple 2 :

8
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

IV. Module Scipy (calcul scientifique : Recherche de zéro, Intégration et


Résolution d’équation différentielle)
Le module scipy est un ensemble de fonctions mathématiques avancées (résolution
d’équations différentielles, méthodes de calcul intégral, calcule de transformées de Fourier,
traitement d’images…..). Il est basé sur les tableaux numpy, complétant ou améliorant la
performance de certaines fonctionnalités.
La bibliothèque scipy présente un grand choix de sous-modules pour le calcul scientifique :

Quelques sous-modules de scipy


scipy.integrate intégration et intégration d’équations différentielles
scipy.optimize optimisation (minimisation, maximisation, recherche de racines)
scipy.interpolate interpolation
scipy.linalg algèbre linéaire
scipy.fftpack transformation de Fourier
1. Recherche de zéro d’une fonction f(x)=0 :
Nous allons voir dans cette partie comment évaluer numériquement une solution d’équation de la
forme: f(x) = 0
Deux méthodes vont être présentées :
 La méthode de dichotomie,
 La méthode de Newton
a) Approche dichotomie :
Ses conditions d’utilisation sont assez simples ; On demande seulement à la fonction d’être
continue et de changer de signe.
Principe :
1. On divise l’intervalle [a, b] en deux.
2. Si f(a) et f ((a + b)/2) sont de signes contraires, on va travailler alors sur [a, (a + b)/2]
(b sera (a + b)/2) ;
3. Sinon, il faudra se placer sur [(a + b)/2, b] (a sera (a + b)/2)
4. Puis on recommence en 1.
Lorsque « f » est une fonction continue sur un intervalle [a, b], à valeurs réelles, avec « f(a) » et
« f(b)» de signe opposé (f(a)*f(b)<0), le théorème des valeurs intermédiaires nous assure que «f»
s’annule entre a et b.

9
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Exemple 1:
Le cas de f(x) = x2 − 2 est simple et démonstratif !

 f(1) = -1 < 0 < 2 = f(2), donc l équation f(x) = 0 possède une solution dans [1, 2].
 La valeur médiane de cet intervalle est 1.5.
 f(1) = -1 < 0 < 0.25 = f (1.5), donc l’équation f(x) = 0 possède une solution dans
[1, 1.5].

 La valeur médiane de cet intervalle est 1.25.


 f (1.25) = −0.4675 < 0 < 0.25 = f (1.5), donc l’équation f(x) = 0 possède une solution
dans [1.25, 1.5].
 …
 f (1.4140625) < 0 < 0.000263273715973= f (1.41430664062)
Donc l’équation f(x) = 0 possède une solution dans [1.4140625, 1.41430664062].
Programme en Python :
Recherche approchée de solution d’une équation par dichotomie

def dichotomie (f, a, b, epsilon):


while b - a > epsilon:
m = (a + b) / 2.
if f(a) * f(m) <= 0:
b = m
else:
a = m
return m
Cette méthode déjà disponible sous python ; La fonction bisect(f,a,b) du module scipy.optimize
permet de déterminer une racine de f dans l’intervalle [a, b] en effectuant une dichotomie.

Exemple 2:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import bisect

def f(x):
return x**2-2

x=np.linspace(-2,2,100)
plt.plot(x,f(x),"b")
r1=bisect (f,-2,-1) # racine de f dans [-2, -1]
r2=bisect (f, 0,2) # racine de f dans [0, 2]
racines= [r1, r2]

plt.plot([-2,2],[0,0],"g-") # une ligne y=0


plt.plot(racines ,[0,0],"r o") # les deux racines trouvées
plt.show()

10
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

b) Approche Newton :
La méthode de Newton est une méthode connu pour la résolution approchée d’une équation
f(x)=0.
Elle permet de définir la suite U dont son premier terme U0, par la relation de récurrence :
Un=Un-1-f (Un-1) / f’ (Un-1)
Programme en Python :
Recherche approchée de solution d’une équation par newton

Cette méthode déjà disponible sous python ; La fonction newton (f, u0, fprime) du module
scipy.optimize permet de calculer, en commençant par u0, une racine de f(x)=0 par la méthode
de Newton (fprime : la dérivée de f).

11
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

2. Intégration numérique d’une fonction :


2.1. Calcul approché d’une intégrale :
Calculer une valeur approchée d’une intégrale n'est en général pas très difficile. Les méthodes les
plus simples consistent à subdiviser régulièrement l'intervalle d'intégration pour approcher le
calcul d’intégral par un calcul d'aires de figures géométriques plus simples (à titre d’exemple
dans la méthode des trapèzes).
Subdivision régulière du segment [a; b] :
Soit [a; b] un intervalle non vide et non réduit à un point (i.e. a<b).
Une subdivision régulière de [a; b] en n+1 points est une suite finie de n+1 réels vérifiant :
a0 = a, an = b et pour tout k ϵ [0; n], ak = a + k*(b − a)/n.

12
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

a. Méthode des rectangles :


Cette méthode d’intégration est basée sur la division de l'aire entre la courbe f(x), l'axe des x et
les droites x = a et x = b, en une multitude de petits rectangles de largeur faible,

On remplace la fonction f par la fonction en escalier qui prend sur chaque segment de la
subdivision, la même valeur à l’extrémité gauche (méthode de rectangle à gauche) de ce segment
que f. cela revient donc à interpoler la fonction f sur le segment [ai, ai+1] par le polynôme de la
grange de degré 0 qui vaut f(ai). l’air du rectangle de base [ai, ai+1] est f(ai).(ai+1-ai), donc :

Car ai+1-ai= (b-a)/n


Evidemment, plus n sera grand et plus la précision du calcul sera grande

Programme en Python :
Calcul approché d’une intégrale : Méthode des rectangles
def rectangle (f, a, b, n):
int_rect = 0
h = (b-a)/n
t = a
for k in range(n):
int_rect += h*f(t)
t += h
return int_rect

b. Méthode des trapèzes:


Principe :
on remplace la courbe représentative de f, sur chaque segment de la subdivision, par le
segment qui joint (ai, f(ai)) à (ai+1,f(ai+1)). Cela revient donc à interpoler la fonction f sur le
segment [ai, ai+1] par le polynôme de Lagrange de degré 1 aux points ai et ai+1.

13
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

La valeur approchée de l’intégrale de f par la méthode des trapèzes est :

Programme en Python :
Calcul approché d’une intégrale : Méthode des trapèzes

Le module Scipy contient un sous-module qui est complètement dédié aux intégrations :
scipy.integrate.
 La fonction quad :
La fonction quad (f, a, b) du module scipy.integrate permet d’intégrer la fonction f(x) sur
l’intervalle [a : b].
Elle retourne un couple contenant la valeur de l’intégrale et une estimation de l’erreur maximale
produite lors de l’intégration. Si la fonction f a plus d’une variable, les valeurs des autres seront
définies par l’argument optionnel args.

Exemple 1:
Si on veut intégrer f(x,y,z) avec y=1 et z=2, on notera : scipy.integrate.quad (f, a, b, args=(1,2)).
N.B. : La variable d’intégration doit être le premier argument de la fonction.

Exemple 2 :

14
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

 La fonction trapz :
La fonction trapz(fx,x) du module scipy.integrate consiste à calculer l’intégral d’une fonction f
par méthode des trapèzes à partir d’une série fx des valeurs de f prise en des points x.
Exemple :

2.2 Résolution d’équations différentielles du premier ordre :


Par définition, une équation différentielle est une équation qui permet de relier une fonction « f »
à ses dérivées.
Exemple : f(x) = αf’(x)+ βf’’(x)
Pour simplifier l’écriture des équations différentielles, on remplace couramment f (x) par y et f
‘(x) par y’.
Exemple : f(x) = α f ’(x)+ β f ’’(x) devient y = α y’+ β y’’
Les équations différentielles considérées doivent être écrites sous la forme : y’ = F (y,t) où F est
une fonction à deux variables « y » et « t » .
Exemple : pour l’équation différentielle : y’(t)+2ty(t)=1 on définit : F (y, t) = 1-2ty ce qui s’écrit
avec Python :
def F (y, t):
return 1-2*t*y # il ne faut pas définir la fonction F
en écrivant : 1-2*t*y(t) INCORRECT

La fonction odeint du module scipy.integrate permet la résolution d’équation différentielle :


Syntaxe : odeint(F,y0,t) Avec :
• F est la fonction apparaissant dans l’équation sous la forme F (y, t) et pas F (t, y),
• y0 est la valeur initiale,
• t est un tableau contenant les valeurs de t qui commence à t0 (Exemple : t=np.linspace(t0,t1,N)).
Exemple 1 : On considère l’équation différentielle d’ordre 1 suivante :

Le but est de calculer puis tracer des valeurs approchées de y entre 0 et 2 pour 5 valeurs
régulièrement espacées.
15
ISSAT Gabès AU : 2016/2017 Sections : BG1, MP1, PC1 & T1

Bibliographie :
1. https://fr.scribd.com/doc/291545781/Cours-Python-pdf
2. http://docplayer.fr/10308708-Numpy-tableaux-de-donnees-multi-dimensionnels-et-matplotlib-
visualisation-en-2d-et-3d-pour-python.html
3. https://fr.scribd.com/document/336148659/cours-MPSI-IPT
4. http://docplayer.fr/17617895-Analyse-scientifique-avec-python.html
5. http://mp2.rupprecht.fr/info_mp/Scipy.pdf
6. http://docplayer.fr/22649926-Ins1-introduction-a-numpy-et-scipy-1-numpy-2-scipy-la-base-a-
importer-pas-necessairement-tous-ensembles-mais-tous-vont-servir-dans-ce-chapitre.html
7. http://docplayer.fr/398723-Les-equations-differentielles.html
8. http://matplotlib.org/1.4.2/_sources/examples/mplot3d/scatter3d_demo.txt

16

Vous aimerez peut-être aussi