Vidéo 30 : La boucle while¶
Boucle while¶
Un problème typique¶
Étant donné un entier \(n\), on cherche un entier noté \(m\) qui soit le premier multiple de 10 supérieur ou égal à \(n\). Si par exemple \(n=42\) alors \(m=50\) : en effet, 50 est bien un multiple de 10 et il n’y en pas d’autre entre 42 et 50. Voici d’autres exemples :
\(n\) | 2038 | 420 | 0 |
\(m\) | 2040 | 420 | 0 |
L’idée à implémenter¶
Les multiples de 10 sont les entiers : \(0, 10, 20, 30\) etc. Ils s’écrivent sous la forme \(10k\) où \(k\) varie à partir de 0.
Pour trouver \(m\), on parcourt les multiples de 10 depuis 0 et on s’arrête une fois qu’on a atteint ou dépassé l’entier \(n\) donné. Autrement dit, on énumère les multiples \(m\) de 10 tant que \(m < n\). Le parcours est montré dans le tableau ci-dessous où on suppose que \(n=42\).
\(k\) | 0 | 1 | 2 | 3 | 4 | 5 |
\(10k < 42\) ? | oui | oui | oui | oui | oui | non |
Implémentation en Python¶
La notion de « dès que », « une fois que » ou de « tant que » est traduite dans le code Python par l’instruction while
.
Le code suivant répond au problème posé :
while_typique.py
1 2 3 4 5 6 7 | n = 42
k = 0
while 10 * k < n:
k = k + 1
print(10 * k)
|
8 | 50
|
On voit (cf. lignes 7 et 8) que la solution au problème est 50.
Analyse de code¶
On passe en revue le code de while_typique.py
.
Vocabulaire de la boucle while
¶
- Lignes 4-5 : ces deux lignes forment une seule et même instruction, dite instruction
while
. - Ligne 4 : l”en-tête de la boucle
while
est la partie qui commence avecwhile
et se termine avant le séparateur : (deux-points). - Ligne 5 : le corps de la boucle
while
qui est le bloc indenté sous les deux-points.
Répétition¶
Une boucle while
répète une action (ligne 5) tant qu’une condition, ici (cf. ligne 4) :
10 * k < n
reste vraie. Plus précisément,
- si la condition est vraie, l’exécution entre dans le corps de la boucle et à la fin du corps de la boucle, la condition est à nouveau testée (d’où le terme de boucle)
- si la condition est fausse, l’exécution du programme va au-delà du corps de la boucle, ici à la ligne 6.
Variable de contrôle¶
Une boucle while
fait souvent appel à une variable de contrôle, ici k
, qui évolue pendant la boucle. Typiquement,
- cette variable est initialisée avant la boucle, ici ligne 2 ;
- cette variable est réaffectée, dans le corps de la boucle
while
, ici par l’instruction ligne 5 ; - la condition à tester (ici ligne 4) est différente d’un tour de boucle à l’autre car elle dépend de
k
qui, entre-temps, a varié.
Remarques¶
- Ligne 4 : dans l’immense majorité des cas, le corps d’une boucle
while
est indenté. - Ligne 1 : il est possible de faire d’autres essais de code en changeant juste la valeur de \(n\). Par exemple, si on change \(n\) en 2038, le programme affichera 2040.
- Il se peut que l’exécution du code n’entre même pas dans le corps de la boucle
while
. Par exemple, si ligne 1, on choisitn=0
au lieu den=42
, le test10 * k < n
(ligne 4) échoue immédiatement et donc le programme continue à la ligne 6 sans même passer par la ligne 5. - À la différence de la syntaxe des boucles while du C et de Java, le booléen évalué avant chaque tour de boucle n’a pas besoin d’être entouré de parenthèses.
Comprendre comment s’exécute une boucle while
¶
Modifions le code précédent while_typique.py
pour mieux comprendre l’exécution de la boucle while
:
while_typique_affichage.py
1 2 3 4 5 6 7 8 9 10 11 12 | n = 42
k = 0
print("avant while", "-> k=", k)
print()
while 10 * k < n:
print("debut while", "k=", k, "-> 10*k=", 10*k)
k = k + 1
print("fin while", "-> k=", k)
print()
print("apres while")
print(10 * k)
|
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | avant while -> k= 0
debut while k= 0 -> 10*k= 0
fin while -> k= 1
debut while k= 1 -> 10*k= 10
fin while -> k= 2
debut while k= 2 -> 10*k= 20
fin while -> k= 3
debut while k= 3 -> 10*k= 30
fin while -> k= 4
debut while k= 4 -> 10*k= 40
fin while -> k= 5
apres while
50
|
En plus du code initial, while_typique_affichage.py
contient des instructions d’affichage (lignes 3, 7, 9 et 11) et des instructions de sauts de ligne (lignes 4 et 10) dans la sortie pour observer l’évolution de k
et de 10 * k
avant, pendant et après la boucle while
.
L’exécution du programme est la suivante :
- Lignes 2 et 7 : la valeur de
k
avant le commencement de la bouclewhile
- Ligne 6 :
k
vaut 0. Le test de la bouclewhile
est effectué : a-t-on0 < 42
? La réponse est oui donc, l’exécution du code continue dans le corps de la bouclewhile
- Les affichages sont effectués :
k
est changé de 0 à 1 (lignes 8 et 16). - Ligne 6 : le test de la boucle
while
est à nouveau effectué : a-t-on \(10 < 42\) ? La réponse est oui et l’exécution entre à nouveau dans le corps de la boucle. Cette opération se répète jusqu’à ce quek = 5
(ligne 8 et ligne 28). - Ligne 6 : le test de la boucle
while
est effectué : a-t-on \(50 < 42\) ? Cette fois, la réponse est non donc l’exécution quitte la boucle et continue lignes 11 et 12, cf. lignes 30 et 31. - Ligne 12 : le résultat affiché (cf. ligne 31) est bien le résultat demandé. Comme le test
10 * k < n
a échoué pour la première fois, c’est qu’on a10 * k >= n
aveck
minimal et c’est bien ce que l’on cherchait.
Calculer le nombre de chiffres d’un entier¶
On donne un entier \(\mathtt{n\geq 0}\) et on cherche le nombre de chiffres de \(\mathtt{n}\) (ce nombre de chiffres sera appelé nchiffres
). Par exemple, si \(\mathtt{n = 2020}\) alors nchiffres = 4
ou encore si \(\mathtt{n = 42}\) alors nchiffres = 2
.
L’idée pour calculer nchiffres
est de compter le nombre de divisions successives de n
par 10 jusqu’à ce que le quotient (entier) soit nul. Par exemple
- le quotient entier de
2020
par 10 est202
, - le quotient entier de
202
par 10 est20
, - le quotient entier de
20
par 10 est2
, - le quotient entier de
2
par 10 est0
.
C’est parce 2020
a justement 4 chiffres qu’on a effectué 4 divisions successives par 10 avant d’obtenir un quotient nul.
Ecrire un code Python utilisant une boucle while
et qui détermine nchiffres
connaissant \(\mathtt{n}\).
Voici quelques exemples de comportements
42 -> 2
2020 -> 4
10 -> 2
7 -> 1
0 -> 1
741520036365253625145211741523636854198541 -> 42
Premier entier pair¶
Ecrire un code qui à partir d’une liste L
d’entiers :
- affiche le premier entier pair rencontré dans la liste L si
L
contient au moins un entier pair, - affiche le nombre \(-1\) s’il n’existe aucun entier pair dans la liste.
Voici quelques exemples de comportement du programme :
[1, 3, 42, 51, 32, 9] -> 42
[1, 3, 42, 51, 33] -> 42
[1, 3, 51, 33] -> -1
[1, 3, 51, 33, 42] -> 42
[42, 82] -> 42
[42] -> 42
[81] -> -1
[] -> -1
Solution
Version for
¶
L=[1, 3, 41, 51, 31, 9]
ok=False
i=0
n=len(L)
for i in range(n):
if L[i]%2==0 and not ok:
print(L[i])
ok=True
if not ok:
print(-1)
Il suffit d’appliquer la technique vue dans le paragraphe Boucle while et parcours de liste.
L=[1, 3, 42, 51, 32, 9]
i=0
n=len(L)
while i<n and L[i]%2 == 1:
i = i + 1
if (i==n):
print(L, "->", -1)
else:
print(L, "->", L[i])
[1, 3, 42, 51, 32, 9] -> 42
- Lignes 6-7 : la boucle
while
parcourt la listeL
jusqu’à ce que la liste soit épuisée ou bien qu’un élément pair soit rencontrée. - Lignes 9-10 : en sortie de boucle, ou bien l’indice
i
est hors de la liste et dans ce cas la liste ne contient aucun élément pair (si un élément pair est présent uniquement en dernière position alors, en sortie de boucle,i
vautn-1
.
Pour traiter le cas de plusieurs listes, au lieu de recopier du code, on place les liste dans une liste tests
et on parcourt la liste tests
pour tester chacune des lignes :
tests = [
[1, 3, 42, 51, 32, 9],
[1, 3, 42, 51, 33],
[1, 3, 51, 33],
[1, 3, 51, 33, 42],
[42, 82],
[42],
[81],
[]]
for L in tests:
i=0
n=len(L)
while i<n and L[i]%2 == 1:
i = i + 1
if (i==n):
print(L, "->", -1)
else:
print(L, "->", L[i])
[1, 3, 42, 51, 32, 9] -> 42
[1, 3, 42, 51, 33] -> 42
[1, 3, 51, 33] -> -1
[1, 3, 51, 33, 42] -> 42
[42, 82] -> 42
[42] -> 42
[81] -> -1
[] -> -1
La petite exponentielle contre le grand produit¶
Trouver le plus grand entier \(n >0\) tel que \(1.0001^n<10000n\) (on trouvera \(n=214893\)).
Solution
Posons a = 1.0001
. Comme a
est très proche de 1, les puissances de a
augmentent mais très lentement. Par exemple :
a=1.0001
print(a**10000)
2.7181459268249255
Toutefois, comme a
est strictement plus grand que 1, le nombre \(\mathtt{a^n}\) peut être rendu aussi grand que l’on veut en choisissant \(\mathtt{n}\) assez grand.
Pour le code lui-même, l’idée est très simple : on compare \(\mathtt{a^n}\) et \(\mathtt{10000\times n}\) en faisant varier \(\mathtt{n}\) suivant les entiers consécutifs jusqu’à ce que le premier dépasse le second. D’où le code :
k=1
while 1.0001**k < 10000*k:
k=k+1
print("n =", k-1)
n = 214893
- Ligne 1 : l’énoncé demande de trouver un entier \(\mathtt{k > 0}\).
- Ligne 6 : en sortie de boucle
while
l’entierk
trouvé est le premier qui vérifie \(\mathtt{1.0001^k \geq 10000\times k}\). C’est l’entierk
précédent qui est tel que l’en-tête de la bouclewhile
est vrai. C’est donc lui la solution du problème.
On peut bien sûr vérifier que le résultat n = 214893
est conforme :
k = 214893
print(k, "->", 1.0001**k < 10000*k)
k = 214894
print(k, "->", 1.0001**k < 10000*k)
214893 -> True
214894 -> False