Download - S1_INFO_2013-2014_TD02
1AB Langage C 2013-2014
1/8
Algorithmique : algorigrammes et pseudo-‐code
Introduction
La chaîne de développement de programmes est synthétisée par le schéma de la page 13 du polycopié. Elle commence bien entendu par la position d’un problème qu’on traduit généralement par un cahier des charges. L’analyse de ce cahier conduit au développement d’un algorithme. Ce n’est qu’une fois celui-‐ci terminé qu’on commence la phase de codage et enfin la phase de tests. Ainsi, il est important de noter que la construction d’un algorithme
-‐ vient AVANT le codage (programmation dans un langage spécifique). -‐ constitue une étape aussi, voire plus, importante que celle du codage.
Un algorithme est une procédure de calcul bien définie qui prend en entrée une valeur, ou un ensemble de valeurs, et qui donne en sortie une valeur, ou un ensemble de valeurs. Il est le fruit d’une méthode logique de résolution d’un problème énoncé, en vue d’être développé dans un langage de programmation. C’est la suite logique des actions à entreprendre pour aboutir à la solution finale et donc construire un programme. La construction d’un algorithme se fait indépendamment du langage de programmation, seules la logique et l’efficacité du programme sont privilégiées. L’algorithme peut de représenter sous plusieurs formes :
-‐ graphique, on dispose d’un algorigramme ou logigramme. -‐ textuelle, on a alors un pseudo-‐code.
L’objectif de ce TD est de vous aider à appréhender ces deux outils avant de vous lancer dans la programmation.
1AB Langage C 2013-2014
2/8
A. Algorigrammes
L’importance du développement d’un algorithme est telle qu’une norme a été développée pour normaliser la façon de représenter un algorithme sous forme de logigramme (ou algorigramme). Il s’agit de la norme ISO 5807. Elle permet de décrire en détail les différents symboles à utiliser pour représenter un algorithme de manière normalisée. Quiconque connaît cette norme reconnaîtra aisément les symboles et comprendra l’algorithme.
A.I. Structure basique d’un algorigramme
A la lecture de la définition d’un algorithme, on comprend qu’un algorigramme a un début et une fin séparés par une multitude d’instructions. Une instruction exécute une opération ou un ensemble d’opérations visant à modifier la valeur d’une variable par exemple, ou encore la forme ou la place d’une information. La norme ISO 5807 propose les éléments graphiques visibles à la figure 1.
Figure 1 : Algorigramme à structure linéaire
Tip 1 : Le début et la fin d’un algorigramme sont tous deux représentés par un rectangle aux coins arrondis. Il ne peut y avoir qu’un seul début, mais plusieurs fins sont possibles. Tip 2 : Une instruction se trouve à l’intérieur d’un rectangle. Tip 3 : Les étapes de l’algorithme sont reliées entre elles par des flèches. Ces flèches indiquent le sens d’exécution du programme. Pour un élément considéré comme une entrée (exemple : lecture de la saisie d’un clavier) ou une sortie (impression à l’écran), le symbole est un parallélogramme.
Figure 2 : Symbole pour une entrée / sortie
Do it 1 : Convertir un algorithme simple en algorigramme Ø Construire l’algorigramme correspondant à
l’algorithme suivant. Un élève arrive à l’ENSEA. Il consulte son emploi du temps, puis il cherche la salle de TD. Il entre et salue son professeur. Il s’assoit, soulagé de ne pas être retard.
A.II. Définition de variables
Une difficulté essentielle dans l’élaboration d’un algorithme est la définition des variables nécessaires et utiles au traitement. Les variables sont des zones réservées dans la mémoire de l’ordinateur. Leur taille et le codage binaire utilisé pour lire ou écrire les données dépendent du type de la variable. Toutes les données traitées dans un programme sont localisées dans des variables.
1AB Langage C 2013-2014
3/8
La déclaration d’une variable réserve un espace mémoire auquel on accède par le nom de cette variable. La valeur d’une variable après sa déclaration est indéfinie. En effet, l’espace mémoire alloué n’est pas « nettoyé », et la variable récupère « ce qui traînait en mémoire ». Il est donc important d’initialiser une variable après sa déclaration. DANS TOUTE LA SUITE, CHAQUE ALGORIGRAMME QUE VOUS CONSTRUIREZ DEVRA OBLIGATOIREMENT
AVOIR POUR PREMIERE INSTRUCTION « DEFINITION ET INITIALISATION DES VARIABLES ». IL VOUS APPARTIENDRA EGALEMENT DE REFLECHIR SUR LES VARIABLES DONT VOUS AUREZ BESOIN.
A.III. Branchements conditionnels : test et décision
L’élève précédent a de la chance : il est arrivé à l’heure. Mais que se passe-‐t-‐il si l’enseignant a une montre qui avance de cinq minutes ? Le fait même de poser la question introduit un branchement conditionnel ou un test : SI. Selon la valeur de l’expression logique (ou condition) testée (VRAI ou FAUX), le programme exécute un groupe d’instructions donné. Comment construit-‐on cette condition ? En utilisant des opérateurs de comparaison couplés à des opérateurs logiques.
A.III.1. Aparté sur la logique booléenne
La logique booléenne est au cœur du dispositif des tests. Une mauvaise évaluation de la condition est la cause principale de dysfonctionnement des tests et donc du programme. A.III.1.1. Opérateurs de comparaison Les ordinateurs étant capables d’interpréter exclusivement des 0 et des 1, les opérateurs de comparaison travaillent sur des nombres (entiers ou réels). Deux nombres A et B peuvent être :
-‐ égaux -‐ différents -‐ A est supérieur (strictement ou égal) à B -‐ A est inférieur (strictement ou égal) à B
A.III.1.2. Opérateurs logiques Les trois opérateurs booléens couramment employés sont le ET, le OU et le NON. Le ET utilise deux opérandes. Son résultat est VRAI quand les deux opérandes sont VRAI, FAUX sinon. A l’inverse, le OU est VRAI dès qu’un seul des deux opérandes est VRAI, et donc FAUX si les deux opérandes sont FAUX. Le NON donne le résultat inverse de son opérande (et donc utilise un seul opérande). Dans le cas d’un test sur des intervalles (valeur comprise entre deux bornes), il est nécessaire de combiner l’utilisation des opérateurs de comparaison et des opérateurs logiques en écrivant que la variable doit être supérieure à la borne inférieure et que la variable doit être inférieure à la borne supérieure. Do it 2 : Etablir des expressions logiques. Ø x supérieur ou égal à 3 Ø y compris strictement entre 1 et 8. Ø Le contraire du test précédent en utilisant le NON, puis
sans utiliser le NON.
A.III.2. Symbole d’un branchement conditionnel
Le test, représenté par un losange, possède une entrée et deux sorties correspondant à des alternatives, mais une et une seule sera active, dépendant de l’évaluation de la condition.
1AB Langage C 2013-2014
4/8
Figure 3 : Symbole d'une structure conditionnelle
Quelques règles simples de graphisme sont à respecter : -‐ les traits des flèches sont horizontaux ou verticaux ; pas de diagonale. -‐ Les directions des alternatives VRAI doivent toutes être identiques. On ne peut pas mettre le cas
VRAI vers le bas pour une condition 1, puis vers la droite pour une condition 2. Do it 3 : Construire des algorigrammes avec branchement conditionnel.
N’oubliez pas de réfléchir sur les variables utiles. Ø Etudier le signe d’un nombre. Ø Etudier la parité d’un nombre. Ø Etudier la responsabilité du port de ceinture. Rappelons les règles suivantes concernant le port
obligatoire de la ceinture : -‐ Le conducteur ne portant pas la ceinture se
voit retirer 3 points de permis et écope une amende de 4ème classe.
-‐ La personne ne portant pas la ceinture est mineure. Le conducteur écope d’une amende de 4ème classe.
-‐ La personne ne portant pas la ceinture est majeure. Celle-‐ci écope d’une amende de 4ème classe.
A.IV. Boucles et répétitions
Supposons maintenant que l’enseignant veut pointer les élèves. Il dispose d’une liste qu’il aura pris soin d’imprimer avant le TD qui lui indique le nombre et les noms des élèves. Do it 4 : Effectuer un pointage des élèves. Ø Supposons pour une question de simplicité que les
élèves soient au nombre de 4, appelés A, B, C et D. En utilisant uniquement des structures conditionnelles, dessiner l’algorigramme permettant de pointer les élèves.
Question 1 : Quel test avez-‐vous effectué après chaque élève ? En existe-‐t-‐il au moins un autre possible ?
Votre algorigramme ainsi défini comporte certainement des séquences qui se répètent. Afin de simplifier la visibilité, et parce que la plupart des langages de programmation le permettent, on peut introduire une boucle. Dans un algorigramme, cela consiste simplement à rediriger une flèche vers une étape antérieure. Bien entendu, pour que l’algorithme puisse atteindre son état final, la boucle doit pouvoir s’arrêter et donc valider (ou ne plus valider) une condition. Il est très important de noter que l’évolution de la variable testée par la boucle s’approche (et non s’éloigne) de la condition d’arrêt. Chaque passage dans la boucle s’appelle une itération.
1AB Langage C 2013-2014
5/8
Figure 4 : Boucle
Do it 5 : Effectuer un pointage des élèves (2). Ø Simplifier l’algorigramme précédent avec une boucle.
Question 2 : Quels sont les changements, autres que la suppression des passages redondantes et l’introduction de la boucle, que vous avez dû apporter à votre algorigramme, en particulier au niveau des tests ?
Considérons maintenant que l’enseignant soit suffisamment tête-‐en-‐l’air pour oublier la liste qu’il a imprimée. Il ne connaît ni les noms des élèves, ni leur nombre.
Question 3 : Quel test lui permettrait alors de savoir s’il a terminé le pointage ?
Ainsi, comme on peut le voir dans cet exemple, on peut distinguer deux types de boucles : -‐ déterministe : on connaît à l’avance le nombre d’itérations, et donc s’en servir comme condition
d’arrêt ; -‐ non déterministe : on ne connaît pas a priori le nombre d’itérations. Certes, un test permettra de
sortir de la boucle, mais le nombre d’itérations peut varier selon les données d’entrée.
Tip 4 : Dans le cas d’une boucle déterministe, on peut établir une condition sans faire appel au nombre d’itérations. La connaissance du nombre d’itérations permet de rendre le test plus simple. Do it 6 : Construire des algorigrammes avec boucles.
Dans chaque cas qui suit, réfléchir aux variables utiles, dire s’il s’agit d’une boucle déterministe ou non et établir un l’algorigramme correspondant.
Ø Additionner les cent premiers entiers. Ø Calculer x puissance y, x et y étant deux entiers
donnés.
Ø Calculer la factorielle de l’entier n. Ø Trouver les puissances de 2 encadrant un nombre
entier.
Ø Décomposer un nombre entier en facteurs premiers. Soient x la variable contenant l’entier donné et n une variable initialisée à 2. Tant que x est différent de 1,
-‐ si le nombre x est divisible par n, affecter à x la valeur x divisée par n et afficher n ;
-‐ sinon, incrémenter n de 1 ; Ø Calculer le PGCD de deux nombres. Algorithme d’Euclide :
L’algorithme continue tant que le reste est différent de zéro, et le PGCD est le dernier reste non nul.
1AB Langage C 2013-2014
6/8
A.V. Sous-‐programmes : modularité
A.V.1. Fonctionnement d’un sous-‐programme
Un sous-‐programme possède la même structure qu’un programme. Il déclare des variables (dites locales), que lui seul connaît, et effectue des traitements dans sa partie instructions. Chaque sous-‐programme implémente un calcul et participe au traitement général du programme. Les autres sous-‐programmes ignorent son mode de fonctionnement interne. Seule l’information échangée via les arguments d’entrée et de retour des modules de traitement est connue. Cette segmentation des traitements améliore le fonctionnement global du programme en dédiant des modules de traitement à des tâches particulières, et facilite ainsi le développement qui se fait par modules. De plus, il devient possible d’optimiser le fonctionnement interne d’un module dans intervenir sur le reste du programme. Dans la phase de conception de l’algorithme global, le développeur doit définir clairement la liste des modules de traitement, leur rôle respectif et leurs interactions réciproques.
Figure 5 : Structure d'un sous-programme et appel du sous-programme dans le programme principal
L’appel du sous-‐programme se fait en utilisant le symbole de deux rectangles encastrés. Do it 7 : Déterminer les N premiers nombres premiers. Pour ce faire, on construit un sous-‐programme qui teste si un nombre est premier, puis on l’utilise pour
afficher ces N premiers nombres premiers. Ø Tester si un nombre est premier. Reprendre l’algorigramme qui décompose un nombre
entier en facteurs premiers. Le nommer Premier. Le modifier pour qu’il retourne 1 si le nombre à décomposer est premier et 0 sinon.
Ø Ecrire l’algorigramme du programme principal qui affiche les N premiers nombres premiers en utilisant le sous-‐programme Premier.
A.V.2. Un saut dans la complexité algorithmique
Le but de tout algorithme est de proposer une solution à un problème posé en minimisant le temps de traitement. Celui-‐ci dépend directement du nombre de calculs mis en œuvre. La complexité algorithmique informe sur le nombre de calculs, et donc sur la performance d’un programme. Un cours d’algorithmique avancé traitera de ces problèmes dans une année ultérieure pour les intéressés. Pour l’heure, il est intéressant et important de noter que la modularité d’un programme permet d’améliorer la complexité algorithmique de façon indépendante pour chaque module, contribuant à grandement améliorer la complexité de l’ensemble.
1AB Langage C 2013-2014
7/8
Do it 8 : Déterminer les N premiers nombres premiers (2). Pour ce faire, on construit un sous-‐programme qui teste si un nombre est premier, puis on l’utilise pour
afficher ces N premiers nombres premiers. Ø Améliorer le sous-‐programme Premier. Pour ce faire, il
est important de remarquer que 2 est le seul nombre premier pair. Il est donc inutile, lorsqu’on cherche les facteurs premiers de s’intéresser aux nombres pairs.
Reprendre l’algorigramme Premier et le modifier afin de diminuer les calculs.
Ø Améliorer le programme principal. La remarque est identique, le nombre 2 est le seul nombre premier pair.
Reprendre l’algorigramme principal et le modifier afin de diminuer les calculs.
Question 4 : Combien de calculs ont été épargnés ? Quel est le gain en temps ?
B. Pseudo-‐code ou métalangage
Le pseudo-‐code ou métalangage permet la description écrite d’un algorithme sans référence à un langage de programmation en particulier. Ainsi, de même que pour un algorigramme, le métalangage s’affranchit des contraintes de programmation pour s’intéresser à l’algorithme. Bien entendu, il utilise les mêmes structures que celles décrites dans la partie algorigramme. Nous allons les passer en revue, puis donner un exemple d’algorithme en pseudo-‐code.
B.I. Traitements logiques en pseudo-‐code
Affectation d’une variable : Variable x initialisée à 5
x ç 5
Entrée d’un nombre x à partir du clavier SAISIR x Sortie d’un nombre x sur l’écran AFFICHER x Branchement conditionnel SI SI <expression du test> ALORS
instruction(s) FINSI
Branchement conditionnel SI…SINON SI <expression du test> ALORS instruction(s) SINON instruction(s) FINSI
Branchement conditionnel CAS OU : La variable x prend un nombre fini de valeurs discrètes.
CAS OU x EGAL valeur 1 : instruction(s) finValeur valeur 2 : instruction(s) finValeur … valeur k : instruction(s) finValeur … valeur n : instruction(s) finValeur FINCASOU
Boucle déterministe POUR x VARIANT DE val_initial A val_finale instruction(s) FINPOUR
Boucle non déterministe TANT QUE <expression du test> FAIRE instruction(s) FINTANTQUE
1AB Langage C 2013-2014
8/8
B.II. Exercices
Do it 9 : Convertir un algorigramme en pseudo-‐code. Ø Convertir l’algorigramme étudiant la parité d’un
nombre.
Ø Convertir l’algorigramme du PGCD. Ø Convertir l’algorigramme amélioré des N premiers
nombres premiers.
Conclusion
Définir correctement un algorithme est donc primordial, car ce sont les solutions qu’il propose qui seront programmées. La qualité et la rapidité du programme final découlent directement de l’algorithme. Des outils tels que les algorigrammes et le pseudo-‐code permettent d’en faciliter la construction en s’affranchissant des problèmes de code.