12 - Boucles non bornées
Nous avons vu les boucles bornées : les boucles qui travaillent en boucle un nombre de fois défini à l'avance.
Nous avons vu les instrutions conditionnelles : comment agir en fonction des besoins.
Voyons aujourd'hui les boucles non bornées : on agit en boucle tant qu'une condition est évaluée à True.
Version non finalisée qui reprend des morceaux de l'ancienne version. A terme, tout va changer.
Evaluation ✎ : questions 07-08-09
1 - Boucle non bornée tant que / while
Voyons maintenant le tant que / while, bien pratique avec les applications graphiques qui ne sont censés s'arrêter que dans certains cas.
On pourrait utiliser un test SI mais cela ne fonctionnerait qu'une fois ...
On pourrait utilser une boucle bornée mais elle finira par s'arrêter...
Boucle non bornée : la boucle while
Heureusement, il existe le test TANT QUE. Il s'agit d'instructions qui seront executés en boucle TANT QUE la condition testée est VRAI.
Puisqu'on ne peut pas connaitre à l'avance le nombre de fois où la boucle d'exécution va être réalisée, on parle également de boucle non bornée : il n'y a pas de nombre limite au bout duquel on quitte la boucle.
Elle se code de la façon suivante :
while condition_pour_boucler :
Comme son nom l'indique, on va donc boucler TANT QUE l'expression condition_pour_boucler
code> est évaluée à True.
C'est comme si nous avions noté ceci :
while condition_pour_boucler == True :
Bien entendu, il est possible que vous avez à l'inverse une condition_pour_sortir
code>.
Nous avons vu qu'il y a deux versions :
La version propre :
while not condition_pour_sortir :
La version explicite
while condition_pour_sortir == False :
Comme pour le IF, c'est l'indentation de 4 espaces qui permet d'indiquer quelles instructions sont à faire en boucle.
Voici à titre d'exemple la façon d'utiliser un while (TANT QUE).
Commençons par un exemple graphique :
- On crée une tortue à des coordonnées et un angle aléatoire.
- On lui demande d'avancer TANT QUE sa coordonnée x est inférieure à 200.
01° Placer ce code en mémoire et visualiser le déplacement de la tortue.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
|
02° En regardant le code, que peut-on dire des valeurs initiales en x et de l'angle de base ?
Avec cette valeur initiale en x, est-on certain de parvenir à rentrer au moins une fois dans la boucle TANT QUE ?
Avec l'angle de base, est-on certain de percuter le "mur" de droite ?
Rappel : s.xcor()
permet de récupérer la coordonnée horizontale du stylo ("x" donc).
...CORRECTION...
Ligne 6 : x = rd.randint(-200, 200)
: on voit que x est inférieure à 200. Comme la condition pour rentrer dans la boucle est (ligne 23) d'être inférieure à 300, nous sommes certain de rentrer au moins une fois.
Pour l'angle, on a (ligne 8) un angle entre -45° et +45° : on va donc percuter le mur.
03° Remplacer la ligne 8 par ceci : l'angle est maintenant aléatoire entre 90° et 180°.
8 |
|
Que va-t-il se passer cette fois au niveau de la boucle TANT QUE
Pourquoi parle-t-on de boucle infinie ?
...CORRECTION...
On ne pourra jamais percuter le mur de droite.
Nous ne sortirons donc jamais de la boucle car la condition restera VRAI à jamais.
D'où le terme "BOUCLE INFINIE".
Condition initiale
Lorsqu'on écrit une boucle TANT QUE, il est impératif de surveiller s'il est possible de rentrer (ou pas) une première fois dans la boucle. Si la condition travaille à partir d'une donnée qui arrivera plus tard, il est alors important de placer une "fausse valeur" dans cette variable de façon à rentrer dans la boucle.
Erreur typique :
19
20
21
22
23
24
25 |
|
L'erreur ? La condition de la ligne 23 a besoin de x alors qu'elle n'est définie qu'en ligne 25 !
Correction possible :
Soit la solution de l'exercice, soit placer une fausse valeur dans x avant la ligne 23.
19
20
21
22
23
24
25
26 |
|
Si nous avions voulu créer une boucle infinie avec nos balles de l'activité précédente, nous aurions donc pu remplacer la boucle POUR réglée à 8000 par une simple boucle TANT QUE réglèe sur VRAI. On trouve ce type de code assez souvent dans les programmes des micro-contrôleurs : on veut que le programme ne s'arrête jamais !
04° Utiliser le code ci-dessous qui contient une boucle infinie. Localiser la boucle et vérifier que l'animation ne s'arrête jamais. Ca peut être long :o)
>>> lancer_animation()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 |
|
2 - Equivalence
Nous avons vu que :
- La boucle bornée POUR / FOR est programmable naturellement en Python avec un for.
- La boucle non bornée TANT QUE / WHILE est programmable naturellement avec un while.
Néanmoins, on peut remplacer les boucles FOR par des boucles TANT QUE et donc dans les programmes les for par des while.
Ce n'est pas "naturel" mais on peut.
Deux fonctions qui de l'extérieur donneront la même chose :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
|
05° Tester les deux versions pour vérifier qu'elles font bien la même chose.
On devrait bien calculer ici 1 + 2 + 3 + 4 + 5 = 15.
>>> somme(5)
15
>>> somme2(5)
15
On remarquera néanmoins qu'utiliser un while alors que l'algorithme théorique montre qu'on va au bout du calcul à chaque fois (boucle bornée) crée au final un code plus compliqué.
- Il faut recréer une variable de boucle x
- Il ne faut pas oublier de l'augmenter de 1 à chaque tour de boucle, sinon on crée une boucle infinie !
Voyons maintenant l'inverse : on peut en réalité coder les boucles non bornées en utilisant un TANT QUE mais également à l'aide d'un POUR. Cela veut dire qu'en terme de programmation, on peut remplacer les while par des for. Mais là, c'est plus compliqué : il faudra l'associer par exemple à la propriété des return dans les fonctions : on sort immédiatement. Cela permettra d'interrompre le déroulement normal de la boucle non bornée qui n'est pas censée s'interrompre justement !
Exemple : deux versions d'une fonction qui renvoie le plus petit carré strictement inférieur à l'entier n que vous avez transmis : on transmet 105, elle renvoie 100 par exemple. Pour 100, elle renvoie 81.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
06° Tester les deux versions du programme en faisant les appels pour une même valeur. 27 devrait provoquer le renvoi de 25 par exemple.
>>> plus_petit_carre_en_dessous2(27)
25
>>> plus_petit_carre_en_dessous2(27)
25
Pour finir et bien comprendre qu'on peut implémenter les boucles des deux façons, proposer une fonction-procédure utilisant un for dont l'effet sera similaire à la fonction ci-dessous, qui contient un while.
1
2
3
4
5
6 |
|
Attention au retour final. La fonction native print n'est là que pour comprendre ce qui se passe sans utiliser le mode pas à pas.
...CORRECTION...
1
2
3
4 |
|
3 - Exos
✎ 07° Expliquer étape par étape comment fonctionne la fonction carre_inf qui renvoie le nombre carré juste inférieur au nombre entier naturel n fourni en paramètre.
Pour 10 à 15, la fonction renvoie 9 (3*3).
Pour 16 à 24, la fonction renvoie renvoie 16 (4*4).
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | def carre_inf(n):
'''Fonction qui renvoie le carré juste inférieur ou égal à n
::param n(int) :: le nombre dont on cherche le carré juste inférieur
::return (int) :: la valeur du carré juste inférieur ou égal à n
'''
nombre = 0
while (nombre+1)*(nombre+1) <= n :
nombre = nombre + 1
return nombre*nombre
x = carre_inf(10)
print(x)
x2 = carre_inf(18)
print(x2)
|
✎ 08° Même question mais avec la fonction carre_inf2 qui fait pareil mais avec un code légerement différent.
Pour 10 à 15, la fonction renvoie toujours 9 (3*3).
Pour 16 à 24, la fonction renvoie toujours renvoie 16 (4*4).
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | def carre_inf2(n):
'''Fonction qui renvoie le carré juste inférieur ou égal à n
::param n(int) :: le nombre dont on cherche le carré juste inférieur
::return (int) :: la valeur du carré juste inférieur ou égal à n
'''
nombre = 0
while nombre*nombre <= n :
nombre = nombre + 1
return (nombre-1)*(nombre-1)
x = carre_inf2(10)
print(x)
x2 = carre_inf2(18)
print(x2)
|
4 - FAQ
Rien pour l'instant
Activité publiée le 01 11 2020
Dernière modification : 01 11 2020
Auteur : ows. h.