Quelques points de programmation Partie 1

Dimension: px
Commencer à balayer dès la page:

Download "Quelques points de programmation Partie 1"

Transcription

1 Quelques points de programmation Partie 1 1) Écrire un programme Un programme est une suite d'instructions. On appelle en général langage de programmation un logiciel (donc aussi un programme) qui va lire ces instructions et agir en conséquence (afficher des choses à l'écran, faire des bruits, écrire des données dans des fichiers, etc.) L'ordinateur traite la liste des instruction dans l'ordre où elles sont écrites. Nous allons parler succinctement ici de trois types d'instructions : Affectation d'une valeur à une variable. Test. Boucle. 2) Un point sur les variables Il est commode (même si c'est en réalité inexact) de voir une variable comme une case mémoire. Par exemple, affecter 3,1 à la variable a revient à placer 3,1 dans la case mémoire a. Chaque variable a un certain type : nombre, chaîne de caractères, liste, etc. Pour nous, au début, c'est surtout le type nombre qui est intéressant. Mais en fait, il y a plusieurs types de nombres. Les langages font en général la différence entre un réel ou «flottant» (type «float») et un entier (type «integer»). «Réel» ou «flottant» signifie un nombre quelconque, ou une approximation décimale, écrite en notation décimale si le nombre est très grand ou très petit. «Entier» signifie un nombre entier relatif. Dans la plupart des langages, les nombres traités sont contenus dans des limites précises. Par exemple, en python, le type «float» concerne des nombres (positifs ou négatifs) dont la valeur absolue est comprise entre et avec une précision de 12 chiffres. En python, il y a une instruction qui permet de connaître le type d'une variable. Elle s'appelle type. >>> a=3.0 >>> type(a) <type 'float'> Remarque 1 : Les >>> en début de ligne signalent qu'on est en mode interactif. Déclaration : en algobox, il faut déclarer chaque variable utilisée, avec son type ; c'est le cas dans beaucoup de langages. En python, ce n'est pas nécessaire : le langage déclare tout seul la variable et son type au moment où on l'utilise (ça s'appelle du «typage dynamique».) Remarque 2 : Le séparateur décimal est un point, pas une virgule. Pour que python comprenne qu'on parle d'un nombre «flottant», et non pas d'un «entier», il suffit donc de l'écrire avec un point. Remarque 3 : En python, une liste se signale par des crochets, par ex : [0, 2.4, 8.6]. 3) Affectation d'une valeur à une variable AFFECTER valeur à variable '='. 4 a PREND_LA_VALEUR 1 5 AFFICHER a 6 FIN_ALGORITHME En python (en mode interactif) : >>> a=1 >>> 1 1/6

2 Remarque 4 : Les deux programmes précédents font la même chose (ils affichent 1, pas trop difficile.) Regardons ce qui se passe si on remplace «a prend la valeur 1» par «a prend la valeur a+1». 4 a PREND_LA_VALEUR a+1 5 AFFICHER a 6 FIN_ALGORITHME En python (mode interactif) : >>> a=a+1 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined On constate en lançant le programme qu'algobox fait la même chose que précédemment (il affiche 1). Cela signifie que lorsqu'on déclare la variable a, il lui affecte par défaut la valeur 0. On peut le vérifier en supprimant la ligne 4 dans le programme. Pour python, c'est différent : pour qu'il comprenne que a est un nombre, il faut lui donner une valeur numérique. L'instruction «a=a+1» lui demande d'ajouter 1 à la variable a, mais comme il ne sait pas ce que vaut a, ni même si a est un «entier» ou un «flottant», il ne sait pas quoi faire. Pour lui, la variable a n'est pas définie. Remarque 5 : Il faut se méfier quand on divise deux entiers en python : >>> a=4 >>> a/3 1 On constate que python effectue une division euclidienne (il donne le quotient entier.) Pour ne pas avoir de problème, il faut «typer» a comme «réel» : >>> a=4.0 >>> a/ Ceci a changé avec la version 3 de python (il donne le quotient décimal). Néanmoins, dans le doute, sauf si on a absolument besoin d'un «entier», il vaut mieux définir des «réels», en entrant les valeurs avec un point. 4) Les tests Ajouter SI... ALORS 'if', 'elif', 'else' ; 'elif' est la contraction de 'else if'. 4 LIRE a 5 SI (a==0) ALORS 6 DEBUT_SI 7 AFFICHER "a est positif et négatif à la fois" 8 FIN_SI 9 SINON 10 DEBUT_SINON 11 SI (a<0) ALORS 12 DEBUT_SI 13 AFFICHER "a est négatif" 14 FIN_SI 15 SI (a>0) ALORS 16 DEBUT_SI 17 AFFICHER "a est positif" 18 FIN_SI 19 FIN_SINON 20 FIN_ALGORITHME Remarque 6 : # -*- coding: utf-8 -*- a=input("que vaut a?") if a==0: print("a est positif et négatif") elif a<0: print("a est négatif") elif a>0: print("a est positif") En python, les blocs d'instructions correspondant à un 'if', un 'elif', un 'else', un 'while', etc. sont déterminés par l'indentation : il faut insérer un certain nombre d'espaces en début de ligne, le même nombre pour toutes les instructions. Par exemple, toutes les instructions à exécuter quand la condition du 'if' est satisfaite seront précédées de 4 espaces. 2/6

3 Remarque 7 : En algobox et en python, dans un test, si la condition est que deux valeurs soient égales, il faut écrire deux signes '='. Ce n'est pas vrai dans tous les langages de programmation. Remarque 8 : En python, bien noter les deux points ' : ' à la fin de chaque condition. Remarque 9 : La première ligne du programme python : # -*- coding: utf-8 -*- explique que les caractères sont codés en Utf 8. Elle est rendue nécessaire par la présence d'un caractère accentué (le «é» de «négatif».) Si vous travaillez sous windows, vous devrez sans doute la remplacer par : # -*- coding: Latin-1 -*- NB : Apparemment, ce problème ne se pose pas avec la version 3 de python. 5) Les boucles «tant que» Ajouter TANT QUE.... 'while'. le programme suivant calcule les termes d'une suite géométrique de premier terme 1 et de raison 1,1 et s'arrête lorsque le calcul donne un nombre supérieur à 3. 4 a PREND_LA_VALEUR 1 5 TANT_QUE (a<=3) FAIRE 6 DEBUT_TANT_QUE 7 a PREND_LA_VALEUR 1.1*a 8 AFFICHER a 9 FIN_TANT_QUE 10 AFFICHER "Fin du calcul" 11 FIN_ALGORITHME a=1.0 while a <= 3: a = 1.1*a print("fin du calcul") Remarque 10 : Insistons lourdement. En python, les deux instructions 'a = 1.1*a ' et '' doivent être précédés du même nombre d'espaces, sinon le programme plante avec un message du type : ' File "exemple_03.py", line 4 ^ IndentationError: unindent does not match any outer indentation level ' Remarque 11 : L'usage des boucles «tant que» demande quelques précautions. D'abord, il faut avoir initialisé correctement la variable sur laquelle porte la condition. Ensuite, il faut s'assurer que le programme sortira effectivement de la boucle à un moment ou à un autre, ce qui n'est pas forcément évident. 6) Les boucles «pour» Ajouter POUR...DE...A. 'for'. le programme suivant calcule 10! (factorielle de 10), c'est à dire compteur EST_DU_TYPE NOMBRE 4 DEBUT_ALGORITHME 5 a PREND_LA_VALEUR 1 6 POUR compteur ALLANT_DE 1 A 10 7 DEBUT_POUR 8 a PREND_LA_VALEUR a*compteur 9 FIN_POUR 10 AFFICHER a 11 FIN_ALGORITHME a=1.0 for compteur in range(10): a=a*(compteur+1) 3/6

4 Remarque 12 : En python, l'instruction 'for' a une forme un peu particulière. Au lieu d'avoir quelque chose du genre 'for compteur from 1 to 10', on a 'for compteur in range(10)'. D'autre part, pourquoi avoir dans la boucle l'instruction 'a=a*(compteur+1)' et pas 'a=a*compteur'? Pour le comprendre, regardons ce que c'est que ce 'range(10)' : >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Ainsi, 'range(10)' crée une liste (ce que signalent les crochets [ ]) de 10 nombres entiers consécutifs commençant à 0. La variable compteur prend successivement toutes les valeurs de cette liste, c'est à dire les entiers de 0 à 9. Nous voulons multiplier a par les entiers de 1 à 10, voilà pourquoi nous devons multiplier a par (compteur+1). Une autre solution est d'écrire : a=1.0 for compteur in range(1,11): a=a*compteur En effet : >>> range(1,11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] On peut aussi spécifier un pas (entier) : >>> range(1,11,3) [1, 4, 7, 10] Cette instruction a l'air peu intuitive a priori ; en fait, elle est très pratique. Programme : >>> liste=["papa", "maman", "Titi", "Toto"] >>> for i in liste:... print("bonjour "+i)... Résultat : Bonjour papa Bonjour maman Bonjour Titi Bonjour Toto Ici la variable i parcourt une liste de mots et non pas une liste de nombres. Le programme est plus lisible et compréhensible qu'avec un compteur numérique. Noter en outre le rôle du «+» comme symbole de concaténation (c'est à dire qu'il sert à «coller» plusieurs morceaux de texte), comme dans algobox. 7) Graphiques Premier exemple : Le programme suivant affiche la représentation graphique de x sin( x) entre π et π. 2 x EST_DU_TYPE NOMBRE 3 y EST_DU_TYPE NOMBRE 4 h EST_DU_TYPE NOMBRE 5 DEBUT_ALGORITHME 6 h PREND_LA_VALEUR x PREND_LA_VALEUR -Math.PI 8 TANT_QUE (x<=math.pi) FAIRE 9 DEBUT_TANT_QUE 10 y PREND_LA_VALEUR sin(x) 11 TRACER_POINT (x,y) 12 x PREND_LA_VALEUR x+h 13 FIN_TANT_QUE 14 FIN_ALGORITHME h=0.01 x=-pi while x <=pi: y=sin(x) plot(x,y,'.') x=x+h En algobox, c'est assez simple : on utilise l'une des deux fonctions 'Ajouter TRACER POINT' ou 'Ajouter TRACER SEGMENT' de l'onglet «Dessiner dans un repère». En python, c'est un peu plus compliqué. D'abord, il faut utiliser des bibliothèques ; une bibliothèque est en quelque sorte un groupe d'instructions supplémentaires correspondant à un thème particulier : mathématiques, base de données, interface graphique, etc. Il y a plusieurs bibliothèques qui s'occupent de graphiques ; matplotlib est l'une d'elles. Elle affiche une fenêtre et permet de zoomer, déplacer la courbe, etc. Pratique. Elle fonctionne à l'aide d'une autre bibliothèque, numpy, qui permet surtout de faire directement des calculs mathématiques sur de gros tableaux de nombres. 4/6

5 Il faut donc utiliser ces deux bibliothèques. Heureusement, on peut les appeler en même temps par l'instruction ''. L'instruction plot(x,y,'.') indique qu'on veut afficher les points de coordonnées (x ; y) ; on peut remplacer '.' par 'o', '+', 'x' pour représenter les points par de petits disques, des croix, etc. L'instruction génère la fenêtre comportant le graphique. Les boutons en bas de la fenêtre graphique permettent de modifier l'affichage de façon interactive. En cliquant sur la croix (4 e bouton), on peut ensuite déplacer la courbe (clic gauche), la compresser ou la dilater (clic droit). On peut aussi zoomer à l'aide de la 5 e touche (loupe), en traçant un cadre à la souris. La première touche (maison) permet de retrouver la fenêtre dans son état initial et les deux flêches permettent de retrouver les différentes valeurs de zoom utilisées. La 7 e touche permet de sauver le graphique. On ferme la fenêtre de la façon habituelle. Il existe une façon plus directe de représenter une fonction : x = arange(-pi, pi, 0.1) y = sin(x) plot(x, y) L'instruction x = arange(-pi, pi, 0.1) fabrique un tableau de valeurs comprises entre π et π avec un pas de 0,1 ; x représente donc ici un tableau ou une liste, pas un nombre unique. On peut le vérifier : >>> x=arange(-pi,pi,0.1) >>> x array([ , , , , , , , , , ,... etc , , , , , , , ]) L'instruction y = sin(x) retourne le tableau des images de x par la fonction sinus. L'instruction plot(x, y) fabrique les points dont les coordonnées sont données par les valeurs correspondantes des tableaux x et y. Ici, les points sont reliés par des segments, c'est l'affichage par défaut. Mais ça ne marche pas pour des valeurs séparées, comme dans l'exemple précédent ; c'est pourquoi on avait ajouté le '.' dans plot. Remarque 13 : La fonction arange() fait partie de la bibliothèque numpy, pas de python standard. Elle ne fonctionnera donc que si on a tapé ou from numpy import * au début du programme. On dispose de nombreuses possibilité pour la présentation. Affichons par exemple les courbes des fonctions sinus et cosinus. 1 # coding: utf x = arange(-2*pi, 2*pi, 0.2) 5 y1 = sin(x) 6 y2 = cos(x) 7 plot(x, y1,'g-o',label='sin(x)') 8 plot(x, y2,'rx--',label='cos(x)') 9 xlabel(unicode('antécédent x','utf8')) 10 ylabel('images') 11 title("courbes des fonctions sinus et cosinus") 12 axis([-pi,pi,-1.2,1.2]) 13 grid(true) 14 legend(loc=2) 16 Ligne 7 : 'g-o' signifie que le tracé est en vert (green), avec des point (o) reliés par des segments(-) ; label='sin(x)' donne un nom à la courbe Ligne 8 : 'rx--' signifie que le tracé est en rouge (red), les points sont représentés par des croix (x) reliées par des segments en pointillé (--). Ligne 9 : xlabel est la légende de l'axe des abscisses ; le mot unicode ainsi que le mot 'utf8' sont nécessaires pour afficher les accents du mot «antécédent». Il faut aussi préciser le codage (ligne 1). Ligne 10 : ylabel est la légende en ordonnée. Pas besoin de préciser le codage puisqu'il n'y a pas d'accents. Ligne 11 : C'est le titre du graphique (situé en haut). Ligne 12 : Précise la taille de l'affichage, sous la forme : [x min, x max, y min, y max ]. Ligne 13 : Affiche la grille. Ligne 14 : Affiche la légende, c'est à dire le nom des courbes, définis aux lignes 7 et 8. Le paramètre entre parenthèse est optionnel et peut prendre les valeurs 0 à 10, correspondant à diverses positions de la 5/6

6 légende sur le graphique. Deuxième exemple : On va afficher (numériquement et graphiquement) les premiers termes de deux suite (a n ) et (b n ) donnant des approximations successives de 2 par la méthode de dichotomie. On pose donc : a 0 = 1 ; b 0 = 2 ; à chaque étape, on calcule c= a+b. 2 Si c 2 2 alors 2 est entre c et b n donc on pose a n+1 = c ; sinon 2 est entre a n et c donc on pose b n+1 = c. On peut programmer ceci de deux façons : Première façon : Deuxième façon : a,b=1.0,2.0 for i in range(10): plot(i,a,'go') plot(i,b,'ro') c=(a+b)/2 if c**2<=2: a=c else: b=c print(a,b,b-a) grid(true) axis([-0.2,10,0.8,2.2]) 1 ère façon : pas de nouveautés, excepté à la ligne 3 : a,b=1.0,2.0 liste_a=[] liste_b=[] for i in range(10): liste_a.append(a) liste_b.append(b) c=(a+b)/2 if c**2<=2: a=c else: b=c print(a,b,b-a) plot(liste_a,'go') plot(liste_b,'ro') grid(true) axis([-0.2,10,0.8,2.2]) L'instruction a,b=1.0,2.0 équivaut à a=1.0 ; b=2.0 ; très pratique. 2 e façon : on construit deux listes : liste_a, qui contient a 0, a 2, a 9 et liste_b, qui contient b 0, b 2, b 9. L'instruction liste_a.append(a) ajoute (append) la valeur a au bout de la liste liste_a. De même pour liste_b.append(b). On construit ensuite les points dont les ordonnées sont les valeurs de liste_a et liste_b. On n'a pas écrit les abscisses : lorsqu'elles sont absentes, le programme considère que ce sont les nombres entiers 0, 1, etc. (c'est ce qui se passe aussi avec un tableur.) Si on avait voulu préciser les abscisses, on aurait écrit : liste_n=range(10) plot(liste_n, liste_a,'go') plot(liste_n, liste_b,'ro') La liste liste_n contient les nombres 0, 1, 2, 9, comme on l'a vu. 6/6