Algorithmique et programmation Licence 1 2. Un langage de spécification Bruno Jobard Sommaire I. Introduction II. Syntaxe et sémantique III. Identification, affectation et typage IV. Structure d'un algorithme V. Définition des données VI. Description des actions VII. Conclusion B. Jobard I. Introduction Ce chapitre est consacré à la présentation d'un langage de spécification qui : ● sert à exprimer des algorithmes ● est facilement lisible ● ● est facilement traduisible dans un langage de programmation a été choisi proche du langage Pascal (utilisé en TP) B. Jobard Sommaire I. Introduction II. Syntaxe et sémantique 1. Syntaxe 2. Sémantique III. Identification, affectation et typage IV. Structure d'un algorithme V. Définition des données VI. Description des actions VII. Conclusion B. Jobard II.1. Syntaxe On appelle syntaxe du langage l'ensemble des règles qui régissent la manière dont les éléments d'un langage doivent être écrits. On l'appelle communément l'orthographe. Un texte qui respecte la syntaxe dans lequel il est écrit est dit syntaxiquement correct. Tout écart de syntaxe est appelé erreur de syntaxe ou erreur syntaxique. B. Jobard II.1. Syntaxe Exemple 2.1 : erreur de syntaxe dans une expression mathématique a=(b–c+d*e Erreur de parenthèsage : une parenthèse ouvrante appelle toujours une parenthèse fermante. B. Jobard II.2. Sémantique On appelle sémantique du langage l'ensemble des règles qui régissent la signification des éléments d'un langage. On l'appelle communément le sens. Un texte peut être syntaxiquement correct et sémantiquement incorrect. B. Jobard II.2. Sémantique Exemple 2.2 : erreur sémantique dans une expression mathématique a=0 c = 12 b = c/a Syntaxiquement correct, mais n'a pas de sens car la division par zéro n'est pas définie. B. Jobard II.2. Sémantique Exemple 2.3 : erreur sémantique dans une phrase en français Mon chat mange avec les oreilles. Syntaxiquement correct, mais complètement aberrante d'un point de vue sémantique. B. Jobard Sommaire I. Introduction II. Syntaxe et sémantique III. Identification, affectation et typage 1. Identification et affectation 2. Typage IV. Structure d'un algorithme V. Définition des données VI. Description des actions VII. Conclusion B. Jobard III.1. Identification et affectation Les données manipulées par un algorithme sont souvent désignées par des noms qui servent à les identifier et à contenir leurs valeurs courantes : – aspects identification(contenant) / valeur (contenu) – zone mémoire / valeur stockée L'action fondamentale qui permet d'associer un contenu à un contenant (une valeur à un nom) est appelée affectation et elle est notée « := » dans notre langage. B. Jobard III.1. Identification et affectation Exemple 2.4 : affectation toto := 10 Cette action consiste à associer la valeur 10 à la donnée toto. B. Jobard III.1. Identification et affectation Exemple 2.5 : affectation soit toto une donnée de valeur 10 et titi une donnée de valeur 2. toto := titi Cette action consiste à prendre le contenu de titi qui est 2 et le mettre dans toto. Le contenu de toto devient 2 (et non plus 10) et le contenu de titi reste 2. B. Jobard III.1. Identification et affectation Exemple 2.6 : affectation soit toto une donnée de valeur 10 et titi une donnée de valeur 2. toto := titi + 5 Le contenu de toto devient 7 (2 + 5) et le contenu de titi reste 2. Dans ce calcul, titi et 5 sont appelés opérandes, le signe + qui désigne la somme est l'opérateur. B. Jobard III.1. Identification et affectation On distingue deux catégories de données dans les algorithmes : – les constantes qui conserve la même valeur durant toute l'exécution de l'algorithme – les variables dont la valeur peut changer par les actions de l'algorithme B. Jobard III.2. Typage Une autre caractéristique fondamentale d'une donnée est son type qui définit : – la nature de ses valeurs (entiers, réels, logiques...) – les opérations qu'on peut lui appliquer (opérations arithmétiques ou logiques...) Les langages de spécification et de programmation fournissent des types de données prédéfinis et permettent d'en définir d'autres par composition des premiers. B. Jobard III.2. Typage Remarque 2.1 : L'utilisation des types de données joue un rôle important dans la vérification des algorithmes et plus particulièrement dans le contrôle de la validité des opérations effectuées. En effet, on ne peut utiliser que les opérations permises par le type considéré. B. Jobard Sommaire I. Introduction II. Syntaxe et sémantique III. Identification, affectation et typage IV. Structure d'un algorithme V. Définition des données VI. Description des actions VII. Conclusion B. Jobard IV. Structure d'un algorithme Dans notre langage de spécification, la structure d'un algorithme s'écrit comme suit : algorithme nom de l'algorithme définition des données début actions de l'algorithme fin B. Jobard IV. Structure d'un algorithme Ajout de commentaires introduits entre (* et *) : (* structure d'un algorithme *) algorithme nom de l'algorithme (* définition des données *) déclaration des constantes définition des types déclaration des variables (* corps de l'algorithme *) début actions de l'algorithme fin B. Jobard Sommaire I. Introduction II. Syntaxe et sémantique III. Identification, affectation et typage IV. Structure d'un algorithme V. Définition des données 1. Le type scalaire 2. Le type tableau VI. Description des actions VII. Conclusion B. Jobard V. Définition des données Dans un langage de spécification on peut prédéfinir autant de types que l'on désire à condition de spécifier leur syntaxe et leur sémantique. Dans notre langage nous nous contentons pour l'heure de prédéfinir les types scalaires de base et le type tableau. B. Jobard V.1. Le type scalaire On appelle type scalaire un type dont les valeurs ne sont pas décomposables. Une donnée de type scalaire est appelée donnée de base. On définit dans la suite les types scalaires suivants : entier, réel, logique, caractère et intervalle. B. Jobard V.1.a. Le type entier Les machines informatiques ne possèdent que des valeurs entières comprises dans un intervalle fini [min, max] de ℤ. – (intervalle dépendant du nombre de bits alloués pour représenter ce nombre – voir cours d'introduction à l'informatique) Opérateurs permis par priorité décroissante : – ** (puissance) – * (multiplication) et / (division) – + (addition) et – (soustraction) aussi fonctions prédéfinies : abs (valeur absolue), rac (racine carrée), etc. B. Jobard V.1.a. Le type entier Remarque 2.2 : À cause de l'intervalle limité des entiers, le résultat d'une somme d'entiers peut sortir de l'intervalle disponible et le nombre stocké sera erroné au regard de la somme souhaitée. Il faut donc être très vigilent pour ne pas commettre d'erreur de débordement. B. Jobard V.1.a. Le type entier Exemple 2.7 : déclaration du type entier constante tmax = 100 variables i, j : entier B. Jobard V.1.b. Le type réel Les valeurs réelles sont aussi définies sur un intervalle [min, max] de ℝ. Mathématiquement, cet intervalle contient une infinité de valeurs. Cependant, en informatique, seul un nombre fini de valeurs sont possibles dans cet intervalle. Un nombre réel exact devra donc être approximé par le nombre disponible le plus proche. Le domaine du calcul numérique est dédié au développement de méthodes fonctionnant avec ces contraintes. Mêmes opérateurs que pour le type entier. B. Jobard V.1.b. Le type réel Exemple 2.8 : déclaration du type réel constantes pi = 3.14 epsilon = 1.0E-4 variables x, y : réel B. Jobard V.1.c. Le type booléen ou logique Il comprend les deux valeurs logiques vrai et faux. Opérateurs de base par priorité décroissante : – ~ (négation) – et – ou B. Jobard V.1.c. Le type booléen ou logique Les opérateurs sont définis par la table suivante : P Q ~P P et Q P ou Q faux faux vrai faux faux vrai faux faux faux vrai faux vrai vrai faux vrai vrai vrai faux vrai vrai B. Jobard V.1.c. Le type booléen ou logique Exemple 2.9 : déclaration du type booléen constantes absent = vrai présent = faux variables test : booléen B. Jobard V.1.d. Le type caractère Ses valeurs sont prises dans le jeu normalisé de caractères ASCII (table de 128 caractères : lettres majuscules, lettres minuscules, chiffres, caractères spéciaux ( ? . ; : / * …), … ) Les constantes de type caractère s'écrivent entre apostrophes. On utilise deux fonctions ord et chr : – ord(c) donne le rang du caractère c dans la table ; – chr(c) donne le caractère de rang c dans la table pour 0 ≤ n ≤ 127 B. Jobard V.1.d. Le type caractère Exemple 2.10 : déclaration du type caractère constantes plus = '+' égal = '=' variables c : caractère B. Jobard V.1.e. Le type intervalle Dans le cas où l'on connaît l'intervalle exact de variation d'un scalaire, on peut le définir par le type intervalle. Les opérateurs applicables à un scalaire de type intervalle sont les mêmes que le type scalaire correspondant. B. Jobard V.1.e. Le type intervalle Exemple 2.11 : déclaration du type intervalle entier constantes tmin = 1 tmax = 100 type indice = tmin..tmax variables i : entier j : 1..tmax k : 1..20 l : indice B. Jobard – j,k et l sont des entiers qui ne peuvent pas sortir de leur intervalle de définition au cours du déroulement de l'algorithme, sinon il y a une erreur de conception. V.2. Le type tableau Une structure de données est une collection de données scalaires qui sont désignées sous le même nom et qui possèdent une organisation spécifique. Les tableaux désignent une structure de données de même type. B. Jobard V.2. Le type tableau Selon leurs dimensions, il représentent soit un vecteur ou une matrice d'éléments de même type. Ils permettent l'accès direct à chacune de leurs données en indiquant sa place dans la structure moyennant un indicage : – v[i] pour accéder au ième élément d'un vecteur v – a[i,j] pour le jème élément de la ième ligne d'une matrice a B. Jobard V.2. Le type tableau Exemple 2.12 : vecteur Soit le vecteur de nom v de 8 éléments suivant : v[1..8] = { 2, 56, 7, 4, 34, 108, 5, 12 } v[5] vaut 34 v[8] vaut 12 B. Jobard V.2. Le type tableau Exemple 2.13 : matrice Soit la matrice de nom a de 3 lignes et de 4 colonnes suivante : 3, 9, 6, 7 a[1..3, 1..4] = 4, 13, 65, 8 9, 60, 72, 30 a[1, 3] vaut 6 a[3, 4] vaut 30 B. Jobard V.2. Le type tableau Exemple 2.14 : déclaration de type tableau types vecteur1 = tableau [1..10] d'entiers vecteur2 = tableau [1..5] d'entiers matrice = tableau [1..5, 1..7] d'entiers variables v1, v2 : vecteur1 v3 : vecteur2 a, b : matrice B. Jobard Sommaire I. Introduction II. Syntaxe et sémantique III. Identification, affectation et typage IV. Structure d'un algorithme V. Définition des données VI. Description des actions 1. Structures alternatives 2. Structures répétitives 3. Les expressions 4. Les abstractions VII. Conclusion B. Jobard VI. Description des actions Un algorithme est une combinaison d'actions séquentielles et de structures de contrôle. Deux catégories de structures de contrôle : – structures alternatives (ou structures de choix) – structures répétitives (ou structures itératives) Voyons les structures les plus classiques : – si alors, si alors sinon – pour, tant que, répéter B. Jobard VI.1. Structures alternatives a) La forme simple Syntaxe : si condition alors actions finsi Sémantique : Si la condition est vraie, on exécute actions et on continue le traitement juste après finsi. Si la condition est fausse, on n'exécute pas actions et on continue le traitement juste après finsi. B. Jobard VI.1. Structures alternatives Exemple 2.15 : valeur absolue d'un nombre a si a < 0 alors a := -a finsi B. Jobard VI.1. Structures alternatives a) La forme générale Syntaxe : si condition alors actions1 sinon actions2 finsi Sémantique : Si la condition est vraie, on exécute actions1, on n'exécute pas actions2, et on continue le traitement juste après finsi. Si la condition est fausse, on n'exécute pas actions1, on exécute actions2 et on continue le traitement juste après finsi. B. Jobard VI.1. Structures alternatives Exemple 2.16 : x le plus grand de deux nombres si a ≥ b alors x := a sinon x := b finsi B. Jobard VI.2. Structures répétitives a) La structure pour (cas croissant) Syntaxe : pour i := vi à vf faire actions finpour Sémantique : i (un entier) est la variable de contrôle qui croit de la valeur vi (valeur initiale) à vf (valeur finale) par pas de 1. Si vi = vf, on exécute actions une fois avec i = vi et on continue le traitement juste après finpour. B. Jobard VI.2. Structures répétitives a) La structure pour (cas croissant) Syntaxe : pour i := vi à vf faire actions finpour Sémantique : Si vi > vf, on n'exécute pas actions et on continue le traitement juste après finpour. Si vi < vf, on exécute actions avec i=vi, puis on recommence avec i=vi+1, puis avec i=vi+2, jusqu'à i=vf compris ; puis on continue après finpour. B. Jobard VI.2. Structures répétitives Exemple 2.17 : somme des n éléments d'un tableau a somme := 0 pour i := 1 à n faire somme := somme + a[i] finpour B. Jobard VI.2. Structures répétitives a) La structure pour (cas décroissant) Syntaxe : pour i := vi bas vf faire actions finpour Sémantique : i (un entier) est la variable de contrôle qui décroit de la valeur vi (valeur initiale) à vf (valeur finale) par pas de 1. Si vi = vf, on exécute actions une fois avec i = vi et on continue le traitement juste après finpour. B. Jobard VI.2. Structures répétitives a) La structure pour (cas décroissant) Syntaxe : pour i := vi bas vf faire actions finpour Sémantique : Si vi < vf, on n'exécute pas actions et on continue le traitement juste après finpour. Si vi > vf, on exécute actions avec i=vi, puis on recommence avec i=vi-1, puis avec i=vi-2, jusqu'à i=vf compris ; puis on continue après finpour. B. Jobard VI.2. Structures répétitives Exemple 2.18 : somme des n éléments d'un tableau a somme := 0 pour i := n bas 1 faire somme := somme + a[i] finpour B. Jobard VI.2. Structures répétitives b) La structure tant que Syntaxe : tant que condition faire actions fintantque Sémantique : La séquence actions est exécutée autant de fois que la condition est vraie. Dès qu'elle devient fausse, on continue le traitement juste après fintantque. B. Jobard VI.2. Structures répétitives Exemple 2.19 : somme des 100 premiers nombres entiers somme := 0 i := 1 tant que i ≤ 100 faire somme := somme + i i := i + 1 fintantque B. Jobard VI.2. Structures répétitives c) La structure répéter Syntaxe : répéter actions jusqu'à ce que condition Sémantique : La séquence actions est toujours exécutée d'abord une fois puis autant de fois que la condition est fausse. Dès qu'elle devient vraie, on continue le traitement juste après jusqu'à ce que. B. Jobard VI.2. Structures répétitives Exemple 2.20 : somme des 100 premiers nombres entiers somme := 0 i := 1 répéter somme := somme + i i := i + 1 jusqu'à ce que i > 100 B. Jobard VI. Description des actions Remarque 2.3 Il a été montré par les théoriciens de l'algorithmique que tout algorithme peut s'exprimer en utilisant uniquement : – des structures alternatives de type si alors sinon – et des structures répétitives de type tant que ou répéter. Quand on utilise des structures en plus, c'est essentiellement pour des raisons de commodité et de lisibilité. B. Jobard VI. Description des actions Remarque 2.4 Les structures répétitives doivent toujours faire l'objet d'un contrôle rigoureux de la part du concepteur de l'algorithme et plus particulièrement concernant les éléments de leur condition d'arrêt. Par exemple, une donnée servant de contrôle à une itération doit toujours apparaître au moins une fois en partie gauche d'une affectation dans le corps de tant que et répéter. B. Jobard VI.3. Les expressions On appelle expression une combinaison d'opérateurs et d'opérandes qui peuvent être des variables ou des constantes. Elle spécifie un calcul dont le résultat est affecté à une variable. L'utilisation des expressions est essentielle en algorithmique. B. Jobard VI.3. Les expressions Exemple 2.21 : expression arithmétique et expression logique x := a + 2 – b y := c et ~d ou e expression arithmétique expression logique B. Jobard VI.3. Les expressions Généralement, interprétation des expressions de gauche à droite avec des priorité identiques x := a+b+c x := a+b-c x := a*b*c x := a*b/c équivalent à équivalent à équivalent à équivalent à x := (a+b)+c x := (a+b)-c x := (a*b)*c x := (a*b)/c équivalent à équivalent à x := a+(b*c) x := (a*b)+c Par contre x := a+b*c x := a*b+c B. Jobard VI.4. Les abstractions Dans les langages de spécification, on peut désigner des traitements complexes soit comme une simple action, soit comme un opérande dans une expression. C'est ce qu'on appelle une abstraction. exemples : – lire(x1, x2, ..., xn) lit en entrée ces valeurs – écrire(x1, x2, ..., xn) écrit en sortie ces valeurs – abs(x) opérande pour la valeur absolue de x – rac(x) opérande pour la racine carrée de x B. Jobard VII. Conclusion Nous avons défini un langage de spécification algorithmique minimal pour pouvoir d'ores et déjà commencer à concevoir et étudier des algorithmes significatifs. Nous l'avons voulu simple de manière à dégager l'utilisateur des détails et précisions relatifs à la programmation. On peut ainsi se concentrer plus sur la logique des algorithmes que sur leur réalisation. Ce langage peut bien entendu être enrichi à loisir selon les besoins. Il va d'ailleurs l'être tout au long de cet enseignement. B. Jobard