Cours d'algorithmique BTS CG et DCG

Théorie et exemples d'algorithmes pour comptables et [futurs] experts comptables

Sommaire



Introduction Algorithmes et programmation, qu'est-ce que c'est ?



Qu'est-ce qu'un algorithme ?



De manière simple, un algorithme peut être vu comme un enchaînement d'actions visant à résoudre un problème donné.

Un plus court chemin trouvé via un algorithme tel que celui de Dijkstra (Google).
Les algorithmes classiques sont dit séquentiels dans le sens où ils sont constitués d'un ensemble d'actions élémentaires, qualifiées d'instruction, qui sont traitées les unes après les autres.

On notera que la définition précédente est sans lien direct avec la notion d'informatique au sens des "ordinateurs". En effet, cette définition générale justifie qu'on puisse dire qu'on exécute des algorithmes tous les jours. Par exemple, lorsqu'on indique un chemin à suivre à un passant dans la rue, on lui propose un algorithme : allez tout droit, prenez la première à gauche, puis tout droit, troisième à droite, etc.

Ainsi, un algorithme décrit finalement une sorte de marche à suivre en vue de solutionner un problème, éventuellement de la vie quotidienne, par exemple : quel est le plus cours chemin entre deux points d'une carte ? C'est le "problème du plus court chemin", illustré ci à droite.


Qu'est-ce qu'un programme ?



C'est le concept de programme qui fait le lien entre algorithmique et informatique. Comme vous le savez sans doute, les appareils informatisés, dont les ordinateurs, ne comprennent que les 0 et les 1. C'est ce qu'on appelle le binaire. Pourtant, les ordinateurs font de nombreuses choses. Cependant, pour qu'ils fassent toutes ses choses, il faut des personnes pour leur dire ce qu'ils doivent faire : les programmeurs, alias les développeurs.

Pour dire à un ordinateur ce qu'il doit faire, il faut lui parler. Et il faut le faire dans un langage qu'il comprenne. Cependant, parler avec des 0 et des 1 s'avère quelque peu difficile. Si bien qu'on a inventé des langages, plus proches du langage humain, lesquels permettent de dire plus facilement à un ordinateur ce qu'il doit faire. Ces langages sont appelés langages de programmation.

Pour que l'ordinateur fasse quelque chose de ce qu'on lui dit :

  • Soit il faut tôt ou tard que ce langage soit transcrit en un ensemble de 0 et de 1 compréhensible par un ordinateur, c'est-à-dire transcrit en langage machine. Ce travail, selon le cas, est réalisé par un assembleur et/ou un compilateur. Un tel langage est appelé langage compilé (exemple : C/C++).
  • Soit il faut tôt ou tard qu'un autre programme joue le rôle d'interprète pour lui-même dire à l'ordinateur ce qu'il doit faire. C'est le travail que réalise un interpréteur, un interpréteur étant lui-aussi une forme de compilateur. Un tel langage est appelé langage interprété (exemples : PHP, JavaScript).

La programmation est l'art de parler aux ordinateurs et le programmeur celui qui leur parle.

Un programme est un algorithme ou un ensemble d'algorithmes, rédigé au moyen d'une langue appelée langage de programmation, dont les instructions peuvent être lues et/ou interprétées par un ordinateur qui les exécutent au fil de sa lecture.

Un individu qui tente de parler à un ordinateur mais n'utilise vraisemblablement pas la bonne langue.

Les langages de programmation sont des langues [vivantes] conçues pour discuter avec les ordinateurs. Le programme est un texte, éventuellement constitué uniquement de 0 et de 1, rédigé dans une langue qui puisse être traduite en langage machine par un compilateur ou interprétée par un autre programme.

Finalement, exécuter un programme consiste à laisser un ordinateur ou un interpréteur lire le programme et effectuer, au fil de sa lecture, les actions qui y sont prescrites.

Les variables Variables et opérations sur les variables



Qu'est-ce qu'une variable ?



Je dirais que la manière la plus simple, et non moins réaliste, de se représenter la notion de variable, c'est de se dire qu'il s'agit d'une case au sein de laquelle on peut inscrire une valeur. On donne un nom à cette case et on peut à tout moment en changer la valeur.

Une variable est une case, plus exactement une "case mémoire", à laquelle on donne un nom et dans laquelle on peut placer une et une seule valeur (un nombre, un texte, etc.), susceptible de varier au cours du temps, c'est-à-dire au fil de l'exécution du programme.

L'opération qui consiste à modifier la valeur d'une variable est appelée une affectation.

Pour utiliser une variable, cette fameuse petite case, on utilise son nom. Il importe dès lors de ne pas confondre le nom de la variable et la valeur de la variable . Lorsqu'on écrit le nom de la variable dans un programme, on utilise en fait sa valeur !


Les types de variables



Une variable est certes une case avec une certaine valeur. Mais sa valeur n'est pas quelconque. Elle a un certain "type" : un nombre entier, une date, une heure, etc. Pourquoi ? Parce qu'un ordinateur ne stocke pas de la même manière un texte, un nombre entier ou encore un nombre décimal.

Aussi, pour qu'un ordinateur puisse comprendre ce qu'il y a dans sa variable, on a souvent besoin (cela dépend du langage de programmation) de préciser son type, c'est-à-dire le type de valeur qu'on peut placer au sein de la variable.

Il existe de nombreux types de variables. On peut même créer ses propres types. Les types les plus élémentaires, les seuls que nous utiliserons ici, sont les suivants :

Type Description
Booléen Il s'agit d'un type qui a uniquement deux valeurs possibles : 0/1, vrai/faux, oui/non ou, généralement, en anglais true ou false.
Entier De manière simple, ce sont tous les nombres, positifs ou négatifs, sans chiffre après la virgule.
Réel De manière simple, ce sont tous les nombres, positifs ou négatifs, avec ou sans chiffres après la virgule.
Chaîne Le type "chaîne de caractères" ou plus simplement "chaîne", est une succession de caractères. En fait, il s'agit d'une sorte de tableau de caractères.
Autres Date, date/heure, heure, chaîne de caractères, tableau et tableau associatif. Nous étudierons les tableaux et tableaux associatifs plus loin dans le cours.


Comprenez bien qu'un ordinateur ne comprend que le binaire. "01000001" par exemple peut avoir plusieurs signification pour un ordinateur :

  • Si "01000001" est un caractère (encodé en UTF8), alors "01000001" représente le caractère "A" pour l'ordinateur.
  • En revanche, si "01000001" est un nombre entier, alors "01000001" représente le nombre 65 pour l'ordinateur.

Autrement dit, si l'on ne précise pas à l'ordinateur le type de variable, c'est-à-dire le type de valeur qu'on peut mettre dans cette fameuse case, l'ordinateur n'y comprendra souvent rien !

Pour information, les langages de programmation nécessitant de préciser le type de chaque variable sont qualifiés de langages fortement typés (exemples : C/C++, Java, VBA). Les autres sont qualifiés de langages faiblement typés (exemples : PHP, JavaScript).


Déclaration et affectation de variable



J'ai trop écrit et vous trop lu. Aussi, déclarons quelques variables, faisons quelques affectations... Bref, regardons ce que cela donne...

Dans ces exemples et tous ceux qui suivent, les algorithmes sont rédigés dans deux langages : en "pseudo-code" d'une part, c'est-à-dire en langue française, et en langage JavaScript d'autre part (un réel langage de programmation). Egalement, on peut visualiser le résultat de l'algorithme dans la "console", à savoir la "boîte noire" accessible via l'onglet "Résultat".

Exemple n°1 : création et affectation d'une variable

// On déclare une variable a. a : entier // On affecte le nombre entier 12 à la variable a. a := 12 // On écrit la valeur de la variable dans la console. ecrire(a) // On modifie la valeur de la variable a. a := 7 // On affiche son nouveau contenu. ecrire(a) // On déclare une variable a. var a; // On affecte le nombre entier 12 à la variable a. a = 12; // On écrit la valeur de la variable dans la console. writeLine(a); // On modifie la valeur de la variable a. a = 7 // On affiche son nouveau contenu. writeLine(a);

Exemple n°2 : création et utilisation de plusieurs variables

// On déclare deux variables. a : chaîne b : chaîne // On attribut une valeur à chacune d'entre elles. a := "Hello" b := "World" // On attribut la valeur de a à b puis celle de b à a b := a a := b // Que vallent a et b ? Affichons leur valeur... ecrire(a) ecrire(b) // On déclare deux variables. var a; var b; // On attribut une valeur à chacune d'entre elles. a = "Hello"; b = "World"; // On attribut la valeur de a à b puis celle de b à a b = a; a = b; // Que vallent a et b ? Affichons leur valeur... writeLine(a); writeLine(b);

Dans l'exemple précédent, on peut croire que la valeur des variables "a" et "b" vont être interverties... Erreur !!! Juste après qu'on a écrit "b := a", la variable "b" vaut "Hello". A la ligne suivante "a := b", on met donc "Hello" dans la variable "a". Finalement, les deux variables, "a" et "b", valent "Hello" et n'ont par conséquent pas été interverties.

Rappelez-vous bien qu'un algorithme s'exécute de manière séquentielle, c'est-à-dire ligne après ligne (instruction après instruction). Si une variable est modifiée, sa modification prend effet dès la ligne suivante !

Exemple n°3 : intervertion de deux variables

// On déclare deux variables plus une troisième, temporaire... a : chaîne b : chaîne tmp : chaîne // On attribut une valeur à chacune d'entre elles. a := "Valeur 1" b := "Valeur 2" // On intervertit les valeurs en utilisant la 3ème variable tmp := a a := b b := tmp // On affiche les valeurs de a et b. Magie ! ecrire(a) ecrire(b) // On déclare deux variables plus une troisième, temporaire... var a; var b; var tmp; // On attribut une valeur à chacune d'entre elles. a = "Valeur 1"; b = "Valeur 2"; // On intervertit les valeurs en utilisant la 3ème variable tmp = a; a = b; b = tmp; // On affiche les valeurs de a et b. Magie ! writeLine(a); writeLine(b);

Attention ! Il convient de bien mettre les chaînes de caractères en guillemets et de ne mettre aucun guillemet autour des nombres.

Très bien, vous savez à présent ce qu'est une variable. Vous aurez compris qu'elle permet de stocker temporairement une valeur dans une sorte de case à laquelle on donne un nom et qu'on peut utiliser en utilisant son nom.

Les opérations arithmétiques



Il s'agit maintenant de pouvoir faire quelque chose du concept de variable que nous avons étudié précédemment. Bien, la première chose qu'on puisse faire, c'est des calculs ! En effet, on peut effectuer des calculs ordinaires et complexes en utilisant des variables. Naturellement, on peut conserver temporairement le résultat du calcul au sein d'une variable.

Opération Opérateur Description
Pseudo-code Javascript
Addition + + Permet d'additionner des nombres entre eux.
Soustraction - - Permet de soustraire des nombres entre eux.
Multiplication x * Permet de multiplier des nombres entre eux.
Division / / Permet de diviser des nombres entre eux. Gardez bien en-tête qu'on peut diviser un entier ou un réel par 0.
Concaténation & + Permet de faire la "somme" de chaînes de caractères, c'est-à-dire de les mettre côte-à-côte.

Quelques calculs :

// On déclare et on affecte directement 2 variables a : entier := 3 b : entier := 4 // On déclare une 3ème variable pour conserver les résultats resultat : entier // On affiche la valeur des variables en faisant une concaténation ecrire("La variable a vaut : " & a) ecrire("La variable b vaut : " & b) // Exemples d'addition et de multiplication resultat = a + b ecrire("Résultat n°1 : " & resultat) resultat = a x b ecrire("Résultat n°2 : " & resultat) // Exemples de variable s'utilisant elle-même resultat = resultat x resultat ecrire("Résultat n°3 : " & resultat) resultat = resultat + 1 ecrire("Résultat n°4 : " & resultat) // On déclare et on affecte directement 2 variables var a = 3; var b = 4; // On déclare une 3ème variable pour conserver les résultats var resultat; // On affiche la valeur des variables en faisant une concaténation writeLine("La variable a vaut : " + a); writeLine("La variable b vaut : " + b); // Exemples d'addition et de multiplication resultat = a + b; writeLine("Résultat n°1 : " + resultat); resultat = a * b; writeLine("Résultat n°2 : " + resultat); // Exemples de variable s'utilisant elle-même resultat = resultat * resultat; writeLine("Résultat n°3 : " + resultat); resultat = resultat + 1; writeLine("Résultat n°4 : " + resultat);


Les opérations logiques



Ci-dessus, nous avons effectué des opérations sur des chaînes (exemple : concaténation) et sur des nombres (exemples : addition, multiplication). A présent, nous allons présenter des opérations sur un type de donnée particulier : le type booléen.

Quant on déclare une variable de type booléen, on la qualifie souvent de variable booléenne. Une telle variable ne peut prendre que deux valeurs : vrai (true) ou faux (false). Un booléen a donc une valeur de vérité.

De même qu'on peut effectuer des opérations arithmétiques sur des variables numériques (des nombres), on peut effectuer des opérations sur des variables booléennes (des booléens). On parle d'opérations logiques ou encore d'opérations booléennes.

Opérateur Description
Pseudo-code Javascript
ET && L'opérateur ET peut être perçu de deux manières :

  • Comme la conjonction de coordination "et". Exemple : "j'ai faim et j'ai soif".
  • Comme l'opération de multiplication entre deux booléens.
OU || L'opérateur OU peut être perçu de deux manières :

  • Comme la conjonction de coordination "ou". Exemple : "j'ai faim ou j'ai soif".
  • Comme l'opération d'addition entre deux booléens.
NON ! L'opérateur NON correspond à la négation. La négation d'une chose vraie est faux et celle d'une chose fausse est vraie. Exemple : si j'ai faim, l'affirmation "je n'ai pas faim est fausse. Au contraire, si je n'ai pas faim, cette même affirmation est vraie.

Partant de ces "définitions", on peut construire ce qu'on appelle une table de vérité. Une table de vérité, pour une opération données (un calcul booléen), permet d'énumérer toutes les combinaisons possibles (tous les calculs possibles) et le résultat qui est associé à chacune d'entre elles.

On se donne deux variables booléennes, a et b. On présente ci-dessous le résultat (la table de vérité) des opérations "a ET b", "a OU b" et "NON a" :

a b a ET b a OU b NON a
faux faux faux faux vrai
faux vrai faux vrai vrai
vrai faux faux vrai faux
vrai vrai vrai vrai faux

Pour l'opération OU, on retiendra bien que si a=vrai et b=vrai, alors a OU b est vrai ! Autrement dit, la phrase "j'ai faim ou j'ai soif" est vraie aussi dans le cas où "j'ai faim et j'ai soif", c'est-à-dire dans le cas où "j'ai faim" est vrai et "j'ai soif" est vrai.

Tous simplement, regardons maintenant ce que cela donne sous forme algorithmique :

// Demande à l'utilisateur de saisir deux booléens. a : booleen := lire("Saisir vrai ou faux (variable a) :") b : booleen := lire("Saisir vrai ou faux (variable b) :") // Affichage des valeurs saisies. ecrire("a vaut : " & a) ecrire("b vaut : " & b) // Déclaration d'une variable pour les résultats de calculs. resultat := booleen // Calcul et affichage du résultat d'opérations booléennes. resultat := a ET b ecrire("a ET b vaut : " & resultat) resultat := a OU b ecrire("a OU b vaut : " & resultat) resultat := NON a ecrire("NON a vaut : " & resultat) // Demande à l'utilisateur de saisir deux booléens. var a = readBoolean("Saisir vrai ou faux (variable a) :"); var b = readBoolean("Saisir vrai ou faux (variable b) :"); // Affichage des valeurs saisies. writeLine("a vaut : " + a); writeLine("b vaut : " + b); // Déclaration d'une variable pour les résultats de calculs. var resultat; // Calcul et affichage du résultat d'opérations booléennes. resultat = a && b; writeLine("a ET b vaut : " + resultat); resultat = a || b; writeLine("a OU b vaut : " + resultat); resultat = !a; writeLine("NON a vaut : " + resultat);

Rappelons que nous avons dit qu'un opérateur ET pouvait être vu comme une multiplication entre booléens et l'opérateur OU comme une addition entre booléens. Dès lors, on ne sera pas supris d'apprendre qu'il y a aussi des priorités de calcul avec les booléens.

Avec les booléens, il faut faire attention aux règles de priorités de calculs. Le cas échéant, on doit donc mettre des parenthèses au bon endroit. En conséquence, on retiendre bien les deux règles suivantes :

  • L'opérateur NON est prioritaire sur le ET et le OU.
  • L'opérateur ET est prioritaire sur le OU.

Ainsi, l'opération a ET b OU c est équivalente à (a ET b) OU c et bel et bien différente de a ET (b ou c).

Pour vous en rendre compte, vous pouvez tester l'exemple suivant en saisissant d'abord a=true, b=true et c=false puis en saisissant ensuite a=false, b=true et c=true :

// Demande à l'utilisateur de saisir trois booléens. a : booleen := lire("Saisir vrai ou faux (variable a) :") b : booleen := lire("Saisir vrai ou faux (variable b) :") c : booleen := lire("Saisir vrai ou faux (variable c) :") // Affichage des valeurs saisies. ecrire("a vaut : " & a); ecrire("b vaut : " & b); ecrire("c vaut : " & c); // Déclaration d'une variable pour les résultats de calculs. resultat := booleen // Calcul et affichage du résultat de calculs. resultat := a ET b OU c ecrire("a ET b OU c vaut : " & resultat) resultat := (a ET b) OU c ecrire("(a ET b) OU c vaut : " & resultat) resultat := a ET (b OU c) ecrire("a ET (b OU c) vaut : " & resultat) // Demande à l'utilisateur de saisir trois booléens. var a = readBoolean("Saisir vrai ou faux (variable a) :"); var b = readBoolean("Saisir vrai ou faux (variable b) :"); var c = readBoolean("Saisir vrai ou faux (variable c) :"); // Affichage des valeurs saisies. writeLine("a vaut : " + a); writeLine("b vaut : " + b); writeLine("c vaut : " + c); // Déclaration d'une variable pour les résultats de calculs. var resultat; // Calcul et affichage du résultat de calculs resultat = a && b || c; writeLine("a ET b OU c vaut : " + resultat); resultat = (a && b) || c; writeLine("(a ET b) OU c vaut : " + resultat); resultat = a && (b || c); writeLine("a ET (b OU c) vaut : " + resultat);

Par ailleurs, il existe quelques relations remarquables sur les booléens qu'on appelle les lois de Morgan :

  • NON (a ET b) = NON a OU NON b
  • NON (a OU b) = NON a ET NON b

Ces propriétés se démontrent fort bien à l'aide de tables de vérité. Par exemple, pour la première relation, on peut procéder comme suit :

  • On établit la table de vérité de "a ET b" en fonction de "a" et de "b". On en déduit celle de "NON (a ET b).
  • On établit la table de vérité de "NON a" et de "NON b" en fonction de "a" et "b". On en déuit celle de "NON a OU NON b".
  • Les tables de vérité de "NON (a ET b)" et "NON a OU NON b" étant identiques, on conclut que ces opérations sont équivalentes.

a b a ET b NON (a ET b) NON a NON b NON a OU NON b
faux faux faux vrai vrai vrai vrai
faux vrai faux vrai vrai faux vrai
vrai faux faux vrai faux vrai vrai
vrai vrai vrai faux faux faux faux


Les opérations de comparaison



Les opérations de comparaison, comme leur nom l'indique, permettent de comparer des valeurs à l'aide d'opérateurs de comparaison.

Dans la lignées des opérations logiques, le résultat d'une opération de comparaison est un booléen.

Il important de noter qu'on ne peut comparer que ce qui est comparable ! Il est par exemple vain d'essayer de comparer un nombre entier à une chaîne de caractère. Egalement, on notera qu'on peut très bien écrire "15 ≤ 3". C'est tout à fait acceptable à ceci près que cette affirmation "15 ≤ 3" est fausse...

// Déclaration d'un booléen comparaison : booleen // Récupération et affichage du résultat d'une comparaison comparaison := 15 ≤ 3 ecrire("15 ≤ 3 donne : " & comparaison) // Récupération et affichage du résultat d'une autre comparaison comparaison := 3 ≤ 15 ecrire("3 ≤ 15 donne : " & comparaison) // Déclaration d'un booléen var comparaison; // Récupération et affichage du résultat d'une comparaison comparaison = 5 <= 3; writeLine("15 ≤ 3 donne : " + comparaison); // Récupération et affichage du résultat d'une autre comparaison comparaison = 3 <= 15; writeLine("3 ≤ 15 donne : " + comparaison);

Voici quelques opérateurs de comparaison usuels :

Opération Opérateur
Pseudo-code Javascript
Egal à = ==
Différent de <> ou ≠ !=
Inférieur à < <
Inférieur ou égal à <=
Supérieur à > >
Supérieur ou égale à >=

// Récupération de deux nombres a : reel := lire("Nombre a :") b : reel := lire("Nombre b :") // Affichage des deux nombres ecrire("a : " & a) ecrire("b : " & b) // Quelques comparaisons et le résultat associé ecrire("a égal à b est : " & (a = b)) ecrire("a différent de b est : " & (a ≠ b)) ecrire("a inférieur à b est : " & (a < b)) ecrire("a inférieur ou égale à b est : " & (a ≤ b)) ecrire("a supérieur à b est : " & (a > b)) ecrire("a supérieur ou égale à b est : " & (a ≥ b)) // Récupération de deux nombres var a = readNumber("Nombre a :"); var b = readNumber("Nombre b :"); // Affichage des deux nombres writeLine("a : " + a); writeLine("b : " + b); // Quelques comparaisons et le résultat associé writeLine("a égal à b est : " + (a == b)); writeLine("a différent de b est : " + (a != b)); writeLine("a inférieur à b est : " + (a < b)); writeLine("a inférieur ou égale à b est : " + (a <= b)); writeLine("a supérieur à b est : " + (a > b)); writeLine("a supérieur ou égale à b est : " + (a >= b));

Nous constatons ci-après que les opérations de comparaison, de même que les opérations logiques, prennent tout leur sens dès lors qu'on les utilise afin de construire des conditions.

Les conditions Structure conditionnelle SI



Qu'est-ce qu'une condition ?



Jusqu'à maintenant, nos algorithmes étaient parfaitement "linéaires" et toutes les instructions (les traitements) étaient exécutées, absolument toutes ! Un concept d'algorithmique est celui de condition.

Les conditions permettent de n'exécuter une ou plusieurs instructions que si une certaine condition est vraie ou, au contraire, en exécuter d'autres si celle-ci n'est pas vraie. Pour ce faire, on utilitise ce qu'on appelle une structure conditionnelle, encore qualifiée de branchement conditionnel ou plus simplement de condition.

Une structure conditionnelle permet d'exécuter une ou plusieurs instructions dans le cas où une condition est vérifiée et, éventuellement, une ou plusieurs autres dans le cas contraire.


Les conditions SI ... SINON SI ... SINON ... FIN SI



Une condition a globalement l'allure suivante :

SI [condition_1] ALORS [instructions_1] SINON SI [condition_2] ALORS [instructions_2] SINON [instructions_3] FIN SI
[condition_1] et [instructions_1] : 1ère condition testée. Si celle-ci est vraie, alors les instructions [instructions_1] sont exécutées.
[condition_2] et [instructions_2] : 2ème condition testées, si la 1ère est fausse. Si cette condition est vraie, les instructions [instructions_2] sont exécutées.
[instructions_3] : si aucune des conditions n'est vraie, les instructions [instructions_3] sont exécutées.

Notez qu'il peut n'y avoir aucun SINON SI ou y en avoir plusieurs. Il peut n'y avoir également aucun SINON.

Illustrons ce concept :

// Demande à l'utilisateur de répondre à deux questions. beau : booleen := lire("Fait-il beau ?") chaud : booleen := lire("Fait-il chaud ?") // On affiche des messages différents selon les réponses fournies SI beau ET chaud ALORS ecrire("Il fait beau et il fait chaud, petit vénard !!!") SINON SI beau ALORS ecrire("Il fait beau, c'est déjà pas mal...") SINON SI chaud ALORS ecrire("Il fait chaud mais pas beau, c'est ballot...") SINON ecrire("Désolé pour vous... Vivement les vacances au soleil...") FIN SI ecrire("Dans tous les cas, le temps sera peut-être meilleur ou pire demain.") // Demande à l'utilisateur de répondre à deux questions. var beau = readBoolean("Fait-il beau ?"); var chaud = readBoolean("Fait-il chaud ?"); // On affiche des messages différents selon les réponses fournies if(beau && chaud){ writeLine("Il fait beau et il fait chaud, petit vénard !!!"); }else if(beau){ writeLine("Il fait beau, c'est déjà pas mal..."); }else if(chaud){ writeLine("Il fait chaud mais pas beau, c'est ballot..."); }else{ writeLine("Désolé pour vous... Vivement les vacances au soleil..."); } writeLine("Dans tous les cas, le temps sera peut-être meilleur ou pire demain.");

Commentons l'algorithme ci-dessus :

  • Les deux premières instruction (lignes 2 et 3) visent de demander à l'utilisateur de répondre par "vrai" (true) ou "faux" (false) à deux question. On récupère les réponses apportées au sein des variables "a" et "b".
  • A la ligne 5, on rencontre une première condition. Si l'utilisateur a répondu vrai (true) aux deux questions, l'instruction ligne 6 est exécutée. Ceci fait, le programme saute immédiatement à la ligne 14, c'est-à-dire qu'il saute à l'instruction se trouvant immédiatement après la fin de la structure conditionnelle (après "FIN SI").
  • Si la condition ligne 5 n'est pas vraie, alors le programme teste la condition suivante, celle ligne 7 (SINON SI). Si celle-ci est vraie, l'instruction ligne 8 est exécutée puis le programme saute à la ligne 14.
  • Si la condition ligne 7 n'est pas vraie, alors le programme teste la condition suivante, celle ligne 9 (SINON SI). Si celle-ci est vraie, l'instruction ligne 10 est exécutée puis le programme saute à la ligne 14.
  • Si aucune condition (SI ou SINON SI) n'est vraie, ce sont les instructions du "SINON" ligne 11 qui sont exécutées. En l'occurrence, si la condition 9 n'est pas non plus vraie, alors l'instruction ligne 12 qui est exécutée et le programme saute finalement à la ligne 14.
  • Finalement, on exécute l'instruction ligne 14.

On retiendra bien qu'à partir du moment où une condition est vérifiée (vraie) :

  • Le programme exécute les instructions qui sont associées à la condition vérifiée (vraie), i.e. celles "à l'intérieur" du SI, du SINON SI ou du SINON.
  • Puis le programme quitte la structure conditionnel, c'est-à-dire qu'il saute directement jusqu'au FIN SI.

Voici un second exemple :

On souhaite automatiser le calcul de la prime annuelle de commerciaux. Leur prime est calculée en pourcentage du chiffre d'affaires (CA) qu'ils ont réalisé sur l'année écoulée. Les règles de calcul sont les suivantes :

Chiffre d'affaires Prime (%) Exemple
≤ 100000€ 0% Un commercial ayant réalisé 25000€ de CA touchera 0€ de prime.
> 100000€ et ≤ 250000€ 3% Un commercial ayant réalisé 150000€ de CA touchera 150000 x 3% = 4500€ de prime.
> 250000€ 5% Un commercial ayant réalisé 500000€ de CA touchera 50000€ x 5% = 25000€ de prime.

Rédiger l'algorithme permettant, à partir d'un chiffre d'affaires saisi par l'utilisateur, de calculer puis d'afficher le chiffre d'affaires, le pourcentage de prime applicable et le montant de la prime du commercial.
// Demande à l'utilisateur de saisir un chiffre d'affaires ca : reel := lire("Chiffre d'affaires du commercial :") // Affichage du CA saisi ecrire("Chiffre d'affaires : " & ca) // Détermination du pourcentage de prime applicable pourcent : reel SI ca <= 100000 ALORS pourcent := 0 SINON SI ca <=250000 ALORS pourcent := 3 SINON pourcent := 5 FIN SI // Affichage du pourcentage applicable ecrire("Prime (%) : " & pourcent & "%") // Calcul du montant de la prime prime : reel := ca x pourcent / 100 // Affichage du montant ecrire("Prime (€) : " & prime & "€") // Demande à l'utilisateur de saisir un chiffre d'affaires var ca = readNumber("Chiffre d'affaires du commercial :"); // Affichage du CA saisi writeLine("Chiffre d'affaires : " + ca); // Détermination du pourcentage de prime applicable var pourcent; if(ca <= 100000){ pourcent = 0; }else if(ca <=250000){ pourcent = 3; }else{ pourcent = 5; } // Affichage du pourcentage applicable writeLine("Prime (%) : " + pourcent + "%"); // Calcul du montant de la prime var prime = ca * pourcent / 100; // Affichage du montant writeLine("Prime (€) : " + prime + "€");

Les boucles Compteurs et structures itératives POUR et TANQUE



Qu'est-ce qu'une boucle ou structure itérative ?



Les algorithmes comporte des traitements répétitifs : calcul de la somme d'une série de nombres, listing des lignes d'une factures, parcours d'un tableau, etc. Parfois même, au moment de la rédaction de l'algorithme, on ne sait pas le nombre exact de répétitions nécessaire à l'accomplissement d'un traitement répétitif.

Afin de pallier cette problématique et d'éviter d'avoir à écrire autant de lignes de "code" que de répétition nécessaire à la mise en oeuvre d'un traitement, la notion de boucle a été introduite.

Une boucle permet d'exécuter un traitement un nombre de fois déterminé ou indéterminé. Ce sont les traitements "à l'intérieur" de la boucle qui sont répétés à chaque "tour de boucle" et chaque "tour de boucle" est qualifié d'itération. Si bien qu'on parle de structure itérative.

Dès que vous sentez que tout ou partie d'un algorithme nécessite de répéter un traitement potentiellement plusieurs fois, c'est que vous avez très certainement besoin d'utiliser une boucle !

Très souvent, lorsqu'on utilise une boucle, on a recours à une variable entière (un entier) qu'on qualifie de compteur. Un compteur est un entier qu'on initialise et qu'on augmente ou diminue à chaque tour de boucle. Lorsqu'on augmente le compteur, on parle d'incrémentation et lorsqu'on le diminue, on parle de décrémentation.

// Initialisation d'un compteur i à 0. i : entier := 0 ecrire("i = " & i) // Incrémentation du compteur. i := i + 1 ecrire("i = " & i) // Incrémentation du compteur. i := i + 1 ecrire("i = " & i) // Incrémentation du compteur. i := i + 1 ecrire("i = " & i) // Initialisation d'un compteur i à 0. var i = 0; writeLine("i = " + i); // Incrémentation du compteur. i = i + 1; writeLine("i = " + i); // Incrémentation du compteur. i = i + 1; writeLine("i = " + i); // Incrémentation du compteur (autre écriture possible) i++; writeLine("i = " + i);


La boucle POUR ... FIN POUR



Nous étudions ici une première structure itérative : la boucle POUR. Cette boucle s'utilise en règle générale avec un compteur. Elle est particulièrement pratique lorsqu'on est capable, lors de l'exécution du programme, de connaître le nombre exact de répétitions nécessaire afin d'accomplir un traitement répétitif.

La boucle POUR a globalement l'allure suivante :

i : entier POUR i:=[début] JUSQU'A [fin] PAS DE [pas] [instructions à répéter] FIN POUR
[début] : valeur initiale du compteur (un nombre entier).
[fin] : valeur finale maximum du compteur.
[pas] : valeur de l'augmentation ou de la diminution du compteur à chaque tour de boucle, ce qu'on appelle "l'incrément" ou "le pas".
[instructions à répéter] : un ou plusieurs traitements (instructions) qu'on souhaite répéter à chaque tour de boucle.

Le plus simple pour comprendre le fonctionnement d'une boucle est très certainement d'étudier et tester quelques exemples. Aussi, on détaille ici un premier exemple puis on en propose quelques autres :

Rédiger l'algorithme permettant de lister les nombres de 0 à 100 sous la forme : 0, 1, 2, ..., 100.
// Déclaration d'un compteur i : entier // Affichage des nombres de 0 à 99 POUR i:=0 JUSQU'A 99 PAS DE 1 ecrire(i & ", ") FIN POUR // Affichage de 100 ecrire("100.") // Déclaration d'un compteur var i; // Affichage des nombres de 0 à 99 for(i=0; i<100; i=i+1){ write(i + ", "); } // Affichage de 100 write("100.");

  • Dans l'algorithme ci-dessus, le traitement répétitif est l'écriture (listing) des nombres. Cela revient à dire "écrire un nombre" et le faire plusieurs fois, ce qui se traduit finalement par l'instruction ligne 5. C'est cette instruction qui est répétée.
  • En pseudo-code, la ligne 4 signifie :
    • On initialise la variable i à 0 ("POUR i=0"). Au premier tour de boucle, i vaut donc 0.
    • On boucle jusqu'à ce que i vaille au moins 99 ("JUSQU'A 99").
    • A chaque tour de boucle, on augmente i de 1 ("PAS DE 1").
    • Conclusion, i va donc valoir successivement 0, puis 1, puis 2, et ainsi de suite jusqu'à 99.
    • Attention ! On fait donc 100 tours de boucles. En effet, 0 à 99, cela fait 100 nombres.
  • En Javascript, la ligne 4 s'écrit légèrement différement quoique le principe reste le même :
    • On initialise bien la variable i à 0 ("i=0").
    • On boucle non plus "JUSQU'A 99" mais tant que "i<100" (ce qui revient au même !)
    • A chaque tour de boucle, on augmente i de 1 ("i=i+1", ce qu'on pourrait écrire aussi "i++").
  • Comme i vaut successivement 0, 1, 2, ..., 99, la ligne 5 nous permet finalement d'écrire "0, " puis "1, ", puis "2, " et ainsi de suite jusqu'à "99, ".
  • La ligne 8 nous permet finalement d'écrire "100." et non "100, ".

Rédiger l'algorithme permettant de lister les nombres de 0 à 100 en comptant de 2 en 2. On souhaite obtenir le résultat suivant : 0, 2, 4, ..., 100.
// Déclaration d'un compteur i : entier // Affichage des nombres de 0 à 98 POUR i:=0 JUSQU'A 98 PAS DE 2 ecrire(i & ", ") FIN POUR // Affichage de 100 ecrire("100.") // Déclaration d'un compteur var i; // Affichage des nombres de 0 à 98 for(i=0; i<99; i=i+2){ write(i + ", "); } // Affichage de 100 write("100.");

Rédiger l'algorithme permettant de rédiger la table de multiplication (de 0 à 10) d'un nombre n choisi par l'utilisateur. On souhaite obtenir le résultat suivant :

0 x n = n
1 x n = 2n
2 x n = 3n
...
10 x n = 10n
// Déclaration d'un compteur et d'une variable pour stocker les résultats i : entier resultat : entier // Saisie d'un nombre entier n : entier = lire("Saisir un nombre entier : ") // On affiche la table de multiplication POUR i:=0 JUSQU'A 10 PAS DE 1 resultat = i x n ecrire(i & " x " & n & " = " & resultat) FIN POUR // Déclaration d'un compteur et d'une variable pour stocker les résultats var i; var resultat; // Saisie d'un nombre entier var n = readInteger("Saisir un nombre entier : "); // On affiche la table de multiplication for(i=0; i<=10; i=i+1){ resultat = i * n; writeLine(i + " x " + n + " = " + resultat); }

Rédiger l'algorithme qui permet :

  • de demander à un utilisateur le nombre n de nombres qu'il souhaite saisir ;
  • de demander à l'utilisateur de saisir de saisir ces nombres ;
  • d'afficher tous les nombres saisis ;
  • d'afficher la somme des nombres saisis.
// Déclaration d'un compteur et d'un entier quelconque i : entier nombre : entier // Récupération du nombre de nombres à saisir n : entier := lire("Combien de nombres souhaitez-vous saisir ?") // Déclaration et initialisation d'une variable pour calculer la somme somme : entier := 0 // Demande à l'utilisateur de saisir n nombre et calcul de la somme POUR i:=1 JUSQU'A n PAS DE 1 nombre := lire("Saisir le nombre n°" & i & ":") ecrire("Nombre n°" & i & " : " & nombre) somme := somme + nombre FIN POUR // Affichage de la somme ecrire("Total : " & somme) // Déclaration d'un compteur et d'un entier quelconque var i; var nombre; // Récupération du nombre de nombres à saisir var n = readInteger("Combien de nombres souhaitez-vous saisir ?"); // Déclaration et initialisation d'une variable pour calculer la somme var somme = 0; // Demande à l'utilisateur de saisir n nombre et calcul de la somme for(i=1; i<=n; i++){ nombre = readInteger("Saisir le nombre n°" + i + ":"); writeLine("Nombre n°" + i + " : " + nombre); somme = somme + nombre; } // Affichage de la somme writeLine("Total : " + somme);

On souhaite rédiger un algorithme permettant d'établir le plan d'amortissement d'une immobilisation. L'amortissement est supposé linéaire. L'immobilisation est supposée acquise le 01/01/N.

Rédiger l'algorithme qui :

  • demande à l'utilisateur de saisir la valeur brute de l'immobilisation ;
  • demande à l'utilisateur de saisir la durée d'amortissement (en années) ;
  • affiche le plan d'amortissement de l'immobilisation.

Le plan d'amortissement aura l'allure suivante :

Année N
VNC début : XXXX
Amortissement : XXXX
Amortissements cumulées : XXXX
VNC fin : XXXX

Année N+1
...
// Déclaration d'un compteur i : entier // Récupération de la durée d'amortissement et de la valeur brute de l'immobilisation duree : entier := lire("Durée d'amortissement (en années) :") valeur : reel := lire("Valeur brute de l'immobilisation :") // Calcul du montant de l'amortissement linéaire amo : reel := valeur / duree // Initialisation de la valeur nette comptable et des amortissements cumulés vnc : reel := valeur amoCumul : reel := 0 // Etablissement du plan d'amortissement POUR i:=0 JUSQU'A duree-1 PAS DE 1 SI i = 0 ALORS ecrire("Année N") SINON ecrire("Année N+" & i) FIN SI ecrire("VND début : " & vnc) ecrire("Amortissement : " & amo) amoCumul := amoCumul + amo ecrire("Amortissements cumulés : " & amoCumul) vnc := vnc - amo FIN POUR // Déclaration d'un compteur var i; // Récupération de la durée d'amortissement et de la valeur brute de l'immobilisation var duree = readInteger("Durée d'amortissement (en années) :"); var valeur = readNumber("Valeur brute de l'immobilisation :"); // Calcul du montant de l'amortissement linéaire var amo = valeur / duree; // Initialisation de la valeur nette comptable et des amortissements cumulés var vnc = valeur; var amoCumul = 0; // Etablissement du plan d'amortissement for(i=0; i<duree; i++){ newLine(); if(i == 0){ writeLine("Année N"); }else{ writeLine("Année N+" + i); } writeLine("VND début : " + vnc); writeLine("Amortissement : " + amo); amoCumul = amoCumul + amo; writeLine("Amortissements cumulés : " + amoCumul); vnc = vnc - amo; }


La boucle TANTQUE ... FIN TANTQUE



Nous étudions ici la deuxième structure itérative la plus courante : la boucle TANTQUE. Cette peut également s'utiliser avec un compteur, mais ce n'est pas forcément sa vocation première.

La boucle TANTQUE permet d'exécuter un traitement tant qu'une condition est vérifiée, c'est-à-dire tant que la condition est vraie.

En quelque sorte, cette boucle est un SI [condition] ALORS [instructions] FIN SI dont les instructions sont répétées tant que la condition est vraie.

La boucle TANTQUE a l'allure suivante :

i : entier TANTQUE [condition] [instructions à répéter] FIN TANTQUE
[condition] : calcul booléen quelconque qui renvoie donc vrai (true) ou faux (false). On peut en conséquence utiliser en outre les opérateurs arithmétiques (ET, OU NON) ainsi que les opérateurs de comparaison (=, <, ≤, ≥, >, ≠).
[instructions à répéter] : un ou plusieurs traitements (instructions) qu'on souhaite répéter à chaque tour de boucle.

Hasardons-nous à proposer deux exemples :

On souhaite développer le jeux du "plus ou moins". Le premier joueur choisit un nombre entre 0 et 999999. Le second joueur doit le deviner.

Rédiger l'algorithme qui :

  • demande au joueur 1 de saisir un nombre compris entre 0 et 999999 ;
  • vérifie que le joueur 1 a bien saisi un nombre entre 0 et 999999. Si tel n'est pas le cas, le joueur 1 doit resaisir un nombre jusqu'à ce qu'il soit effectivement dans la bonne fourchette.
  • demande au joueur 2 de deviner le nombre saisi par le joueur 1. Si le joueur 2 trouve la solution, le jeu s'arrête. Dans le cas contraire, l'algorithme indique au joueur 2 s'il doit saisir un nombre plus petit ou plus grand ;
  • ne se termine que lorsque le joueur 2 à trouver la solution.
// Déclaration de variables solution : entier := -1 proposition : entier := -1 // Demande au joueur 1 de saisir un nombre tant qu'il n'est pas compris entre 0 et 999999 TANTQUE solution < 0 OU solution > 999999 solution = lire("Joueur 1, veuillez saisir un nombre compris entre 0 et 999999 :") FIN TANTQUE // Demande au joueur 2 de deviner la solution tant qu'il n'a pas deviné TANTQUE proposition ≠ solution proposition = lire("Joueur 2, devinez le nombre saisi par joueur 1 :") SI proposition > solution ALORS ecrire("C'est moins !") SINON SI proposition < solution ALORS ecrire("C'est plus !") FIN SI FIN TANTQUE // Affichage de la solution ecrire("La solution est bien : " & solution) // Déclaration de variables var solution = -1; var proposition = -1; // Demande au joueur 1 de saisir un nombre tant qu'il n'est pas compris entre 0 et 999999 while(solution < 0 || solution > 999999){ solution = readInteger("Joueur 1, veuillez saisir un nombre compris entre 0 et 999999 :"); } // Demande au joueur 2 de deviner la solution tant qu'il n'a pas deviné while(proposition != solution){ proposition = readInteger("Joueur 2, devinez le nombre saisi par joueur 1 :"); if(proposition > solution){ writeLine("C'est moins !"); }else if(proposition < solution){ writeLine("C'est plus !"); } } // Affichage de la solution writeLine("La solution est bien : " + solution);

On souhaite développer un algorithme qui permette de saisir et d'afficher le détail d'une facture ainsi que d'en calculer le prix total. Le détail de la facture est supposé constitué de produits où le produit a un nom, un prix et est acheté en certaines quantités. Le taux de TVA est supposé être de 20%. Le nombre de produits achetés est susceptible de varier d'une facture à une autre.

Rédiger l'algorithme qui :

  • demande à l'utilisateur s'il souhaite (true/false) ajouter un nouveau produit ;
  • demande à l'utilisateur de saisir le nom du produit et son prix, ;
  • demande à l'utilisateur de saisir la quantité de produit acheté par produit ;
  • affiche les informations saisies par l'utilisateur ;
  • affiche le prix total HT, le montant de TVA et le prix total TTC de la facture ;
// Déclaration de variables nomProduit : chaîne prixProduit : réel qteProduit : entier totalHT : réel := 0 totalTVA : réel := 0 totalTTC : réel := 0 ajouter : booléen := vrai // Tant que l'utilisateur souhaite ajouter des produits, on boucle TANTQUE ajouter // Récupération des saisies de l'utilisateur nomProduit := lire("Nom du produit :") prixProduit := lire("Prix unitaire :") qteProduit := lire("Quantité :") // Affichage des saisies ecrire("Achat de '" & nomProduit & "' (quantité : " & qteProduit & ", prix : " & prixProduit & ")") totalHT := totalHT + qteProduit x prixProduit // On demande à l'utilisateur s'il veut ajouter un autre produit ajouter := lire("Souhaitez-vous ajouter un nouveau produit ?") FIN TANTQUE // Affichage des totaux de la facture ecrire("Total HT : " & totalHT) totalTVA := totalHT x 0,20 ecrire("Total TVA : " & totalTVA) totalTTC := totalHT + totalTVA ecrire("Total TTC : " & totalTTC) // Déclaration de variables var nomProduit; var prixProduit; var qteProduit; var totalHT = 0; var totalTVA = 0; var totalTTC = 0; var ajouter = true; // Tant que l'utilisateur souhaite ajouter des produits, on boucle while(ajouter){ // Récupération des saisies de l'utilisateur nomProduit = read("Nom du produit :"); prixProduit = readNumber("Prix unitaire :"); qteProduit = readInteger("Quantité :"); // Affichage des saisies writeLine("Achat de '" + nomProduit + "' (quantité : " + qteProduit + ", prix : " + prixProduit + ")"); totalHT = totalHT + qteProduit * prixProduit; // On demande à l'utilisateur s'il veut ajouter un autre produit ajouter = readBoolean("Souhaitez-vous ajouter un nouveau produit ?"); } // Affichage des totaux de la facture writeLine("Total HT : " + totalHT); totalTVA = totalHT * 0.20; writeLine("Total TVA : " + totalTVA); totalTTC = totalHT + totalTVA; writeLine("Total TTC : " + totalTTC);

Les tableaux Les variables de type tableau



Les tableaux



Un concept algorithmque que nous n'avons pas étudié jusque-là est celui de tableau. Il importe de bien comprendre qu'il ne s'agit pas d'un tableau au sens visuel du terme (exemple : un tableau Excel).

Au sens algorithmique, un tableau peut être perçu comme une forme de variable un peu particulière constituée non plus d'une case mais d'un ensemble de cases successives : la case 0, la case 1, la case 2, etc.

Le "n° de la case" est appelé indice ou index. Le nombre de cases est appelé taille du tableau.

Attention ! Selon le langage de programmation, la première case du tableau est celle à l'indice 0 ou celle à l'indice 1. Ainsi, selon le langage de programmation, si une variable de type tableau comporte N cases, la dernière case sera la N-ième ou la (N-1)-ième.

Voici un exemple de création de tableau :

// Déclaration d'un tableau de chaînes de caractères jours : chaînes[] // Initialisation du tableau jours := ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"] // Affichage du premier et du dernier jour de la semaine ecrire(jours[0]) ecrire(jours[6]) // Déclaration d'un tableau constitué de 7 chaînes de caractères var jours; // Initialisation du tableau jours = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]; // Affichage du premier et du dernier jour de la semaine writeLine(jours[0]); writeLine(jours[6]);

  • Si un tableau est un type de variable, les case du tableau ont elles-aussi un type ! Dans l'exemple ci-dessus, les cases du tableau sont de type "chaîne de caractères".
  • Pour manipuler une case d'une tableau, on utilise son "indice" (lignes 6 et 7).
  • On utilise les crochets [ et ] pour préciser la case du tableau qu'on utilise.

Les tableaux sont intéressants en ce qu'ils permettent de stockées temporairement une série de valeurs : une série statistique, une liste de prix voire une liste de produits ou encore d'utilisateurs. Plus encore, on peut "parcourir" un tableau.

En utilisant une boucle, on peut parcourir un tableau, c'est-à-dire :

  • Récupèrer la taille N du tableau.
  • Passer en revue les cases du tableau avec une boucle faisant N tours

De fait, on peut effectuer de multiples opérations sur les tableaux. Nous n'évoquons ici que les quelques opérations le plus élémentaires :

Création d'un tableau initialement vide :

nombres : entier[] var nombres = [];

Bien entendu, on peut choisir un nom de variable autre que "nombres" et créer un tableau avec des éléments de type "entier" ou de tout autre type : réel, chaîne, etc.

Initialisation d'un tableau :

nombres := [1, 1, 2, 3, 5, 8] var nombres = [1, 1, 2, 3, 5, 8];

Ajout d'un élément (d'une case) à la fin d'un tableau :

nombres[] = 10 nombres.push(10);

Modification d'un élément (d'une case) d'un tableau :

nombres[6] = 13 nombres[6] = 13;

Récupération de la taille d'un tableau (nombre de cases) :

n : entier := taille(nombres) var n = nombres.length;

Parcours d'un tableau :

i : entier POUR i:=0 JUSQU'A n-1 PAS DE 1 ecrire("Nombre n°" & (i+1) & " :" & nombres[i]) FIN POUR var i; for(i=0; i<n; i++){ writeLine("Nombre n°" + (i+1) + " : " + nombres[i]); }

Finalement, voici deux exemples à étudier sereinement et attentivement pour bien comprendre le fonctionnement des tableaux :

On souhaite tout bonnement conserver et afficher les jours de la semaine.

Rédiger l'algorithme qui :

  • conserve la liste des jours de la semaine ;
  • affiche les jours de la semaine.

Les notes et coefficients sont temporairement conservées dans des tableaux.
// Déclaration de variables jours : chaînes[] i : entier n : entier // Initialisation du tableau jours := ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"] // Parcours des jours de la semaine ecrire("Les jours de la semaine :") POUR i:=0 JUSQU'A 6 PAS DE 1 ecrire(jours[i]) FIN POUR // Déclaration de variables var jours; var i; var n; // Initialisation du tableau jours = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]; // Parcours des jours de la semaine writeLine("Les jours de la semaine :"); for(i=0; i<7; i++){ writeLine(jours[i]); }

On souhaite développer un algorithme qui permette de calculer la moyenne pondérée des notes d'un élève.

Rédiger l'algorithme qui :

  • demande à l'élève de saisir une note puis un coefficient ;
  • demande à l'élève s'il souhaite (oui/non) ajouter une nouvelle note ;
  • calcule et affiche la moyenne.

Les notes et coefficients sont temporairement conservées dans des tableaux.
// Déclaration de variables notes : reel[] coefficients : reel[] ajouter : booleen := vrai // Tant que l'élève souhaite ajouter des notes TANTQUE ajouter // Ajout d'une note à la fin du tableau notes[] := lire("Note :") // Ajout d'un coefficient à la fin du tableau coefficients[] := lire("Coefficient :") // Demande à l'élève s'il souhaite ajouter une nouvelle note ajouter := lire("Ajouter une nouvelle note ?") FIN TANTQUE // Déclaration de variables i : entier n : entier := taille(notes) sommeNotes : reel := 0 sommeCoefficients : reel := 0 // On calcule la somme des (notes x coefficients) et celle des coefficients POUR i:=0 JUSQU'A n-1 PAS DE 1 sommeNotes := sommeNotes + notes[i] x coefficients[i] sommeCoefficients := sommeCoefficients + coefficients[i] FIN POUR // On calcule puis on affiche finalement la moyenne moyenne : reel := sommeNotes / sommeCoefficients ecrire("Moyenne : " & moyenne) // Déclaration de variables var notes = []; var coefficients = []; var ajouter = true; // Tant que l'élève souhaite ajouter des notes while(ajouter){ // Ajout d'une note à la fin du tableau notes.push(readNumber("Note :")); // Ajout d'un coefficient à la fin du tableau coefficients.push(readNumber("Coefficient :")); // Demande à l'élève s'il souhaite ajouter une nouvelle note ajouter = readBoolean("Ajouter une nouvelle note ?"); } // Déclaration de variables var i; var n = notes.length; var sommeNotes = 0; var sommeCoefficients = 0; // On calcule la somme des (notes x coefficients) et celle des coefficients for(i=0; i<n; i++){ sommeNotes = sommeNotes + notes[i] * coefficients[i]; sommeCoefficients = sommeCoefficients + coefficients[i]; } // On calcule puis on affiche finalement la moyenne moyenne = sommeNotes / sommeCoefficients; ecrire("Moyenne : " + moyenne);


Les tableaux associatifs



Ci-avant, nous avons vu ce qu'étaient des tableaux au sens de l'algorithmique et de la programmation. En particulier, on se rappelle que les index ou indices des éléments d'un tableau sont des nombres entiers. Là réside la principale différence entre un tableau et un tableau associatif.

Un tableau associatif est une variable similaire à un tableau à ceci près que les indices ou index ne sont pas forcément des entiers. Il peut par exemple s'agit de chaîne de caractères. L'index ou indice est dès lors appelé clef. Un tableau associatif permet d'associer une valeur à une clef.

Déclaration d'un tableau associatif intialement vide :

jours : tableau associatif var jours = {};

Initialisation d'un tableau associatif :

jours := { "Lundi" : "Monday", "Mardi" : "Tuesday", "Mercredi": "Wednesday", "Jeudi": "Thursday", "Vendredi": "Friday", "Samedi": "Saturday", "Dimanche": "Sunday" } var jours = { "Lundi" : "Monday", "Mardi" : "Tuesday", "Mercredi": "Wednesday", "Jeudi": "Thursday", "Vendredi": "Friday", "Samedi": "Saturday", "Dimanche": "Sunday" };

Ajout ou modification d'un élément (d'une case) du tableau associatif :

jours["Dimanche"] := "Sunday" jours["Dimanche"] = "Sunday";

Suppression d'un élément (d'une case) du tableau associatif :

supprimer(jours["Dimanche"]) delete jours["Dimanche"];

Ajout ou modification d'un élément (d'une case) du tableau associatif :

jours["Dimanche"] := "Sunday" jours["Dimanche"] = "Sunday";

Parcours d'un tableau associatif :

clef : chaîne POUR CHAQUE clef DANS jours ecrire(jours[clef]) FIN POUR var clef; for(clef in jours){ writeLine(jours[clef]); }

Les fonctions et procédures Création de sous-programmes



Qu'est-ce qu'un sous-programme ?



Lorsqu'on réalise un programme ou un algorithme, on divise généralement le problème en sous-problèmes élémentaires plus simples à apprivoiser. En pratique, un programme est la résultante de multiples programmes combinés les uns aux autres.

De plus, on rappelle qu'un algorithme est destiné à solutionner un problème donné. Or, nombreux sont les problèmes générique qui reviennent très régulièrement (exemple : calcul d'une moyenne ou d'une moyenne pondérée). Aussi, afin d'éviter de développer indéfiniment les mêmes programmes, on est amené a créer des programmes réutilisables.


Que sont une fonction et une procédure ?



Les fonctions et procédures sont des algorithmes réutilisables auxquels on attribue un nom. Ils permettent de résoudre un problème souvent récurrent à partir de données fournies. Les données fournies sont appelés des paramètres.

La différence entre une procédure et une fonction réside dans le fait qu'une retourne une et une seule valeur.

De fait, nous avons déjà été amenés à utiliser des fonctions et procédures, par exemple la fonction "lire" et la procédure "ecrire" :

prenom : chaine := lire("Quel est votre prénom ?") ecrire("Bonjour " & prenom & " !") var prenom = read("Quel est votre prénom ?"); writeLine("Bonjour " + prenom + " !");

Dans l'exemple ci-dessus, on utilise la fonction "lire" nous retourne la valeur saisie par l'utilisateur. La procédure "ecrire" ne retourne rien et permet uniquement d'écrire dans la console.

Par ailleurs, lorsqu'on utilise les fonctions et les procédures, il faut bien distinguer :

  • La définition de la fonction ou procédure : c'est l'algorithme à proprement parler, lequel décrit la succession de traitements accomplie par la fonction ou la procédure. La définition d'une fonction ou procédure ne fait rien !
  • L'utilisation, appelé "appel" de la fonction : c'est l'utilisation concrète de l'algorithme. On "appelle" le fonction ou la procédure en lui passant des données (paramètres) concrètes. C'est lors de cet ou ces appels que la fonction ou procédure fait quelque chose !


Définir et utiliser une fonction ou une procédure



Avant toute chose, pour utiliser une fonction ou une procédure, il faut la définir ! En d'autres termes, il faut lui donner un nom, dire quelles sont les données dont elle a besoin en entrées (les paramètres) et finalement dire ce qu'elle fait lorsqu'on l'utilise.

La définition d'une procédure a globalement l'allure suivante :

PROCEDURE [nom]([parametre] : [type], [parametre] : [type], ...) [instructions] FIN PROCEDURE function [nomProcedure]([parametre], [parameter], ...){ [instructions] }


La définition d'une fonction a globalement l'allure suivante :

FONCTION [nom]([parametre] : [type], [parametre] : [type], ...) : [type de retour] [instructions] RETOURNER [valeur de retour] FIN FONCTION function [nom]([parametre], [parameter], ...){ [instructions] return [valeur de retour]; }

Tout cela est un peu flou, je vous l'accorde... Gardons en tête que ce qui précède nous permet de créer une fonction ou procédure qui, tant qu'on ne l'utilise pas, ne fait absolument rien.

Aussi, il faut encore utiliser la fonction ou procédure :

L'utilisation d'une procédure, également appelé appel de procédure, a l'allure suivante :

[nom]([parametre], [parametre], ...) [nom]([parametre], [parametre], ...);

L'utilisation d'une fonction, également appelé appel de fonction, a l'allure suivante :

resultat := [nom]([parametre], [parametre], ...) resultat = [nom]([parametre], [parametre], ...);

Que de paroles ! Passons aux exemples, cela vaudra mieux...


Exemples de fonctions et procédures



Calcul d'intérêts simples

On souhaite développer une fonction "calcValeurAcquise" qui calcule et retourne la valeur acquise en fin de période par un capital placé à intérêts simples pendant une certaine durée.

La fonction prend en entrées les paramètres suivants :

  • La valeur initiale $c_{0}$ du capital ;
  • Le taux d'intérêt $i$ du placement ;
  • La durée du $n$ du placement.

On rappelle que la valeur actuelle du capital en fin de période vaut : $c_{n} = c_{0} \times (1 + n \times i)$
// Définition de la fonction "calcValeurAcquise" FONCTION calcValeurAcquise(c0 : reel, i : reel, n : entier) : reel RETOURNER c0 x (1 + n x i) FIN FONCTION // Utilisation de la fonction "calcValeurAcquise" capital : reel := lire("Capital initial (en euros) :") taux : reel := lire("Taux d'intérêt (en %) :") / 100 duree : reel := lire("Durée du placement (en années) :") valeur : reel := calcValeurAcquise(capital, taux, duree) ecrire(capital & "€ placés pendant " & duree & " an(s) au taux de " & taux & "%.") ecrire("Valeur acquise en fin de période : " & valeur) // Définition de la fonction "calcValeurAcquise" function calcValeurAcquise(c0, i, n){ return c0 * (1 + n * i); } // Utilisation de la fonction "calcValeurAcquise" var capital = readNumber("Capital initial (en euros) :"); var taux = readNumber("Taux d'intérêt (en %) :"); var duree = readInteger("Durée du placement (en années) :"); var valeur = calcValeurAcquise(capital, taux/100, duree); writeLine(capital + "€ placés pendant " + duree + " an(s) au taux de " + taux + "%."); writeLine("Valeur acquise en fin de période : " + valeur);

Calcul du coût d'un emprunt

On souhaite développer une fonction "calcMensualite" qui calcule la mensualité associée à un emprunt à intérêts composés.

La fonction prend en entrées les paramètres suivants :

  • Le montant $c_{0}$ du capital emprunté ;
  • Le taux d'intérêt annuel $i$ de l'emprunt ;
  • La durée $n$ exprimée en mois de l'emprunt ;
  • Le montant mensuel de la prime d'assurance $a$ de l'emprunt.

On rappelle que l'on peut calculer une annuité constante, ou mensualité constante en l'occurrence, en utilisant la formule suivante : $$mensualite = a + c_{0} \times \frac{i}{1-(1+i)^{-n}}$$
Pour simplifier l'algorithme, on utilisera les fonctions suivantes :
  • En pseudo-code : $puissance(a, n) = \overbrace{a \times a \times ... \times a}^{n fois}$
  • En javascript : $Math.pow(a, n) = \overbrace{a \times a \times ... \times a}^{n fois}$
// Définition de la fonction "calcMensualite" FONCTION calcMensualite(c0 : reel, i : reel, n : entier, a : reel) : reel RETOURNER a + c0 x i / (1 - puissance(1 + i, -n)) FIN FONCTION // Utilisation de la fonction "calcMensualite" capital : reel := lire("Capital initial (en euros) :") taux : reel := lire("Taux d'intérêt (en %) :") duree : reel := lire("Durée du placement (en années) :") assu : reel := lire("Prime d'assurance mensuelle (en euros) :") mensualite : reel := calcMensualite(capital, taux/100/12, duree*12, assu) ecrire(capital & "€ emprunté pendant " & duree & " an(s) au taux de " & taux & "% (assurance : " & assu & "€).") ecrire("Mensualité : " & mensualite) // Définition de la fonction "calcMensualite" function calcMensualite(c0, i, n, a){ return a + c0 * i / (1 - Math.pow(1 + i, -n)); } // Utilisation de la fonction "calcMensualite" var capital = readNumber("Capital initial (en euros) :"); var taux = readNumber("Taux d'intérêt (en %) :"); var duree = readInteger("Durée du placement (en années) :"); var assu = readNumber("Prime d'assurance mensuelle (en euros) :"); var mensualite = calcMensualite(capital, taux/100/12, duree*12, assu); writeLine(capital + "€ emprunté pendant " + duree + " an(s) au taux de " + taux + "% (assurance : " + assu + "€)."); writeLine("Mensualité : " + mensualite);

Ecriture de vente

On souhaite développer une procédure "ecritureVente" qui affiche une écriture comptable de vente à partir d'informations fournies.

On retient les hypothèses suivantes :

  • Le taux de TVA est de 20% ;
  • Le compte de produit est le compte 707000 ;
  • Le compte client est le compte fédérateur 411000 ;
  • La livraison est comptabilisée dans le compte 708500.

La procédure prend en entrées les paramètres suivants :

  • La montant HT de la vente ;
  • Le montant HT des frais de port.
// Définition de la procédure "ecritureVente" PROCEDURE ecritureVente(venteHt : reel, portHt : reel) SI vente > 0 ET port ≥ 0 ALORS tva : reel := (venteHt + portHt) x 0.2 total : reel := venteHt + portHt + tva ecrire("411000 | Client. | Débit : " & total) ecrire("707000 | Ventes de marchandises. | Crédit : " & venteHt) SI port > 0 ALORS ecrire("708500 | Ports et frais accesoires facturés. | Crédit : " & portHt) FIN SI ecrire("445710 | TVA sur ABS. | Crédit : " & tva) FIN SI FIN FONCTION // Utilisation de la procédure "ecritureVente" vente : reel := lire("Vente HT :") port : reel := lire("Port HT :") ecritureVente(vente, port) // Définition de la procédure "ecritureVente" function ecritureVente(venteHt, portHt){ if(vente > 0 && port >= 0){ var tva = (venteHt + portHt) * 0.2 var total = venteHt + portHt + tva writeLine("411000 | Client. | Débit : " + total); writeLine("707000 | Ventes de marchandises. | Crédit : " + venteHt); if(port > 0){ writeLine("708500 | Ports et frais accesoires facturés. | Crédit : " + portHt); } writeLine("445710 | TVA sur ABS. | Crédit : " + tva); } } // Utilisation de la procédure "ecritureVente" var vente = readNumber("Vente HT :"); var port = readNumber("Port HT :"); ecritureVente(vente, port);

Calcul d'une moyenne arithmétique

On souhaite développer la fonction "moyenne" qui retourne la moyenne arithmétique d'une série de nombres. La série de nombres prend la forme d'un tableau.
// Définition de la fonction "moyenne" FONCTION moyenne(nombres : reel[]) : reel // Déclaration et initialisation de variables moyenne : reel := 0 n : entier := taille(nombres) i : entier // Calcul de la somme des nombres POUR i:=0 JUSQU'A n-1 PAS DE 1 moyenne := moyenne + nombres[i] FIN POUR // Retour de la somme des nombres divisé par le nombre de nombres RETOURNER moyenne / n FIN FONCTION // Utilisation de la fonction "moyenne" liste : reel[] := [5,10,15,20] resultat : reel := moyenne(liste) ecrire("Moyenne : " & resultat) // Définition de la fonction "moyenne" function moyenne(nombres){ // Déclaration et initialisation de variables var moyenne = 0; var n = nombres.length; var i; // Calcul de la somme des nombres for(i=0; i<n; i++){ moyenne = moyenne + nombres[i]; } // Retour de la somme des nombres divisé par le nombre de nombres return moyenne / n; } // Utilisation de la fonction "moyenne" var liste = [5,10,15,20]; var resultat = moyenne(liste); writeLine("Moyenne : " + resultat);


Fonction et procédure récursives



Quoique nous ne feront ici qu'évoquer le principe sans plus de détail, le concept de fonction récursive ou procédure récursive est fondamental et fort pratique en programmation.

Les fonctions (resp. procédures) récursives sont des fonctions qui s'appellent elles-mêmes.

En effet, rien n'empêche qu'une fonction ou qu'une procédure s'utilise elle-même. Nous ne voulons pour le montrer que le cas d'école suivant :

On souhaite développer la fonction "factorielle" qui permet de calculer la factorielle "n!" d'un nombre entier n positif.

Principe : $n! = n \times (n-1) \times (n-2) \times ... \times 1$
Exemple : $4! = 4 \times 3 \times 2 \times 1 = 24$
Exception : $0! = 1$
// La fonction récursive "factorielle" FONCTION factorielle(n : entier){ SI n = 0 ALORS RETOURNER 1 SINON SI n > 0 RETOURNER n x factorielle(n-1) SINON ERREUR "On ne peut calculer la factorielle que des nombres positifs." FIN SI FIN FONCTION // Utilisation de la fonction factorielle n : entier := lire("Saisir un nombre :") resultat : entier := factorielle(n) ecrire(n & "! = " & resultat) // La fonction récursive "factorielle" function factorielle(n){ if(n == 0){ return 1; }else if(n > 0){ return n * factorielle(n-1); }else{ throw "On ne peut calculer la factorielle que des nombres positifs."; } } // Utilisation de la fonction factorielle var n = readInteger("Saisir un nombre :"); var resultat = factorielle(n); writeLine(n + "! = " + resultat);