Chapitre 427 minDébutant
Boucles pour, tant que et répéter
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- écrire une boucle
Pour,TantQueouRépéter … Jusqu'à, en pseudo-code et en Python ; - choisir la boucle adaptée à un problème ;
- construire un accumulateur : somme, produit ou compteur ;
- imbriquer deux boucles et éviter les boucles infinies.
8 exercices corrigés1 schéma
Une boucle répète un bloc d'instructions : un nombre de fois connu à l'avance avec la boucle Pour, ou tant qu'une condition reste vraie avec la boucle TantQue et sa variante Répéter … Jusqu'à. Ce chapitre montre comment choisir la bonne boucle, comment la construire (initialisation, mise à jour, résultat final) et comment éviter la boucle infinie et l'erreur d'un tour en trop.
Pourquoi des boucles ?
Afficher les nombres de 1 à 5, tu peux l'écrire en cinq lignes. De 1 à 1 000, non. Et compter les tickets d'un fichier dont tu ne connais pas la taille, c'est impossible sans boucle. Une boucle décrit une fois un traitement qui s'exécutera autant de fois que nécessaire.
Chaque passage dans le corps de la boucle s'appelle une itération (ou un tour). Le programme du BTS insiste : les structures de contrôle sont le cœur de l'algorithmique, et les évaluations sont centrées sur elles. Ce chapitre est le plus important du cours.
La boucle Pour
La boucle Pour répète un bloc pour chaque valeur d'un compteur, d'une valeur de départ à une valeur d'arrivée. On l'utilise quand le nombre de tours est connu avant d'entrer dans la boucle.
Pour i de 1 à 5 Faire
Afficher(i, " × 7 = ", i × 7)
FinPour
for i in range(1, 6):
print(i, "× 7 =", i * 7)
1 × 7 = 7
2 × 7 = 14
3 × 7 = 21
4 × 7 = 28
5 × 7 = 35
À chaque tour, le compteur prend la valeur suivante, automatiquement. Tu n'écris jamais i ← i + 1 dans une boucle Pour.
En pseudo-code, les deux bornes sont incluses : Pour i de 1 à 5 fait 5 tours. En Python, range(début, fin) s'arrête avant fin : pour aller de 1 à 5, on écrit range(1, 6). C'est la source n° 1 des erreurs de traduction.
| Pseudo-code | Python | Valeurs de i | Tours |
|---|---|---|---|
Pour i de 0 à 4 | range(5) | 0, 1, 2, 3, 4 | 5 |
Pour i de 1 à 5 | range(1, 6) | 1, 2, 3, 4, 5 | 5 |
Pour i de 0 à n - 1 | range(n) | 0 à n − 1 | n |
Pour i de 0 à 10 pas 2 | range(0, 11, 2) | 0, 2, 4, 6, 8, 10 | 6 |
Pour i de 10 à 1 pas -3 | range(10, 0, -3) | 10, 7, 4, 1 | 4 |
Pour i de 5 à 4 | range(5, 5) | aucune | 0 |
Python sait aussi parcourir directement les éléments d'une liste ou les caractères d'une chaîne, sans compteur :
for serveur in ["web01", "web02", "bdd01"]:
print("Sauvegarde de", serveur)
for lettre in "SIO":
print(lettre)
C'est la forme à privilégier quand tu n'as pas besoin de la position. Les deux formes de parcours d'un tableau sont comparées au chapitre 7.
La boucle TantQue
La boucle TantQue répète un bloc tant qu'une condition est vraie. La condition est testée avant chaque tour : si elle est fausse dès le départ, le bloc n'est jamais exécuté. On l'utilise quand on ne sait pas à l'avance combien de tours il faudra.
Un capital de 1 000 € est placé à 3 % par an. Au bout de combien d'années aura-t-il doublé ?
Algorithme Doublement
Variables
capital : réel
annees : entier
Début
capital ← 1000
annees ← 0
TantQue capital < 2000 Faire
capital ← capital × 1,03
annees ← annees + 1
FinTantQue
Afficher(annees, " ans, capital : ", capital)
Fin
capital = 1000.0
annees = 0
while capital < 2000:
capital = capital * 1.03
annees = annees + 1
print(annees, "ans, capital :", round(capital, 2))
24 ans, capital : 2032.79
Impossible d'écrire une boucle Pour ici : le nombre d'années est justement ce qu'on cherche.
Trois éléments doivent être présents dans toute boucle TantQue :
- L'initialisation des variables de la condition, avant la boucle (
capital ← 1000). - La condition, testée à chaque tour (
capital < 2000). - La mise à jour, dans le corps, d'au moins une variable de la condition, pour que celle-ci finisse par devenir fausse (
capital ← capital × 1,03).
La boucle Répéter … Jusqu'à
La boucle Répéter exécute le bloc puis teste la condition. Le bloc est donc exécuté au moins une fois. Attention au sens : on répète jusqu'à ce que la condition soit vraie ; c'est une condition d'arrêt, l'inverse de celle du TantQue.
L'usage typique est la saisie contrôlée : on demande une valeur, et on redemande tant qu'elle est invalide.
Répéter
Afficher("Note entre 0 et 20 ?")
Saisir(note)
Jusqu'à note ≥ 0 ET note ≤ 20
Python n'a pas de boucle Répéter. On l'écrit avec une boucle while True (infinie en apparence) dont on sort par break quand la condition d'arrêt est vraie :
while True:
note = float(input("Note entre 0 et 20 ? "))
if 0 <= note <= 20:
break
print("Note enregistrée :", note)
On peut aussi écrire un TantQue avec une première saisie avant la boucle. C'est un peu plus long, mais sans break :
note = float(input("Note entre 0 et 20 ? "))
while note < 0 or note > 20:
print("Valeur incorrecte.")
note = float(input("Note entre 0 et 20 ? "))
print("Note enregistrée :", note)
Remarque comment la condition s'inverse en passant d'une version à l'autre : on répète jusqu'à 0 ≤ note ≤ 20, c'est-à-dire tant que note < 0 OU note > 20 (loi de De Morgan, chapitre 2).
TantQue ou Répéter : le test avant ou après
TantQue … Faire | Répéter … Jusqu'à | |
|---|---|---|
| Moment du test | Avant chaque tour | Après chaque tour |
| Nombre minimal de tours | 0 | 1 |
| Sens de la condition | Condition pour continuer | Condition pour s'arrêter |
| En Python | while condition: | while True: … if arret: break |
| Usage typique | Calcul jusqu'à un seuil, recherche | Saisie contrôlée, menu |
Choisir la bonne boucle
| Question | Réponse | Boucle |
|---|---|---|
| Connais-tu le nombre de tours avant d'entrer ? | Oui (n notes, 12 mois, chaque caractère) | Pour |
| Le traitement doit-il s'exécuter au moins une fois ? | Oui (saisie, menu) | Répéter |
| Sinon | On s'arrête sur une condition | TantQue |
Toute boucle Pour peut s'écrire avec un TantQue (on gère le compteur à la main), mais pas l'inverse. Utilise quand même le Pour dès que c'est possible : il est plus court et il ne peut pas boucler à l'infini.
# La même boucle, deux écritures
for i in range(1, 6):
print(i)
i = 1
while i <= 5:
print(i)
i = i + 1
Construire une itération
Le programme décrit la construction d'une boucle en trois temps : la préparation (initialiser les variables), l'itération elle-même (la mise à jour à chaque tour) et la mise en forme finale (ce qu'on fait du résultat après la boucle). Applique-les dans cet ordre et la plupart des boucles s'écrivent seules.
Exemple : la moyenne de n notes saisies.
// Préparation
somme ← 0
// Itération
Pour i de 1 à n Faire
Saisir(note)
somme ← somme + note
FinPour
// Mise en forme finale
moyenne ← somme / n
Afficher(moyenne)
Une aide pour vérifier une boucle : formuler ce qui est vrai à la fin de chaque tour. Ici : « après le tour i, somme contient la somme des i premières notes ». Si c'est vrai au premier tour, et que chaque tour le conserve, c'est vrai au dernier : somme contient la somme des n notes. Cette phrase s'appelle un invariant de boucle. On ne te demandera pas de démonstration, mais la formuler dans ta tête te dit tout de suite si l'initialisation est la bonne.
Accumulateurs : somme, produit, compteur
Trois motifs reviennent dans presque tous les exercices. Ils s'appuient tous sur une affectation récursive : la variable est mise à jour à partir de sa propre valeur.
| Motif | Initialisation | Mise à jour | Pourquoi cette initialisation |
|---|---|---|---|
| Somme | somme ← 0 | somme ← somme + x | 0 est l'élément neutre de l'addition |
| Produit | produit ← 1 | produit ← produit × x | 1 est l'élément neutre de la multiplication |
| Compteur | nb ← 0 | Si condition Alors nb ← nb + 1 | Au départ, on n'a rien compté |
Les symboles Σ (somme) et Π (produit) des maths se traduisent directement par ces motifs. La somme des entiers de 1 à n, Σ i, et la factorielle n! = Π i = 1 × 2 × … × n :
n = 100
somme = 0
for i in range(1, n + 1):
somme = somme + i
print("Somme de 1 à", n, ":", somme)
n = 5
produit = 1
for i in range(1, n + 1):
produit = produit * i
print(n, "! =", produit)
Somme de 1 à 100 : 5050
5 ! = 120
Python a des raccourcis : somme += i équivaut à somme = somme + i (de même -=, *=, //=). Ils sont courants en Python, en C# et en JavaScript ; en pseudo-code, écris l'affectation complète.
Les boucles imbriquées
Une boucle peut en contenir une autre. Pour chaque tour de la boucle externe, la boucle interne fait tous ses tours. Si l'externe fait n tours et l'interne m, le corps interne s'exécute n × m fois.
for i in range(1, 4):
ligne = ""
for j in range(1, 6):
ligne = ligne + str(i * j) + "\t"
print(ligne)
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
"\t" est une tabulation, qui aligne les colonnes. La variable ligne est réinitialisée à chaque tour de la boucle externe : chaque ligne repart de zéro.
Les bornes de la boucle interne peuvent dépendre du compteur externe. Le programme cite explicitement ce cas (« itérations en dépendance »), en le limitant à deux niveaux :
n = 4
for i in range(1, n + 1):
print("*" * i)
*
**
***
****
Ici la boucle interne est cachée dans "*" * i (répéter i fois). Écrite explicitement, elle fait i tours au tour i : 1 + 2 + 3 + 4 = 10 étoiles en tout.
Sortir d'une boucle : break et continue
Python propose deux instructions pour modifier le déroulement d'une boucle :
breaksort immédiatement de la boucle ;continuepasse directement au tour suivant.
tickets = [12, 0, 7, -1, 3]
for t in tickets:
if t < 0:
print("Valeur sentinelle : arrêt")
break
if t == 0:
continue
print("Ticket", t)
Ticket 12
Ticket 7
Valeur sentinelle : arrêt
Elles sont pratiques, mais elles cachent la condition de sortie au milieu du corps. En pseudo-code d'examen, préfère une condition de boucle explicite (un TantQue avec un booléen trouve, par exemple) ; garde break pour la boucle Répéter traduite en Python.
Les erreurs classiques
| Erreur | Symptôme | Correction |
|---|---|---|
| Boucle infinie | Le programme ne s'arrête pas | Vérifier que le corps modifie une variable de la condition |
| Un tour de trop ou de moins (off-by-one) | Il manque le dernier élément, ou IndexError | Vérifier les bornes : range(1, n + 1) pour aller jusqu'à n ; < ou ≤ dans le TantQue |
| Accumulateur mal placé | Le total ne contient que le dernier élément | Initialiser avant la boucle |
Condition de Répéter non inversée | La saisie valide est redemandée, l'invalide acceptée | Jusqu'à prend la condition d'arrêt |
| Test d'égalité sur des réels | while x != 1.0 ne s'arrête jamais | Comparer avec < ou >, ou utiliser un compteur entier |
Compteur modifié dans un Pour | Nombre de tours imprévisible | Utiliser un TantQue |
Le dernier piège des réels mérite un exemple : en ajoutant 0,1 dix fois à 0, on n'obtient pas exactement 1.
x = 0.0
for i in range(10):
x = x + 0.1
print(x, x == 1.0)
0.9999999999999999 False
Une boucle while x != 1.0: x = x + 0.1 ne s'arrêterait donc jamais. Utilise un compteur entier (for i in range(10)) ou une comparaison while x < 1.0.
Exercices
Exercice 1 sur 8 Traduire des bornes Réussi À revoir
Traduis chaque boucle en Python avec range et donne le nombre de tours.
Pour i de 1 à 12Pour i de 0 à n - 1Pour i de 2 à 20 pas 2Pour i de 10 à 0 pas -1Pour i de 1 à n
Voir la réponseMasquer la réponse de l'exercice 1
range(1, 13): 12 tours.range(n): n tours.range(2, 21, 2): 2, 4, …, 20, soit 10 tours.range(10, -1, -1): 10, 9, …, 0, soit 11 tours. Avecrange(10, 0, -1), on s'arrêterait à 1.range(1, n + 1): n tours.
Tu avais trouvé ?
Exercice 2 sur 8 Combien de tours ? Réussi À revoir
Pour chaque boucle, donne le nombre de tours et la valeur finale de k.
# A
k = 0
for i in range(3, 9):
k = k + 1
# B
k = 1
while k < 100:
k = k * 3
# C
k = 10
while k > 10:
k = k - 1
Voir la réponseMasquer la réponse de l'exercice 2
- A :
range(3, 9)donne 3 à 8, soit 6 tours ;kvaut 6. - B :
kprend les valeurs 3, 9, 27, 81, 243 ; 5 tours ;kvaut 243 (le test243 < 100est faux, on sort). - C : 0 tour, car
10 > 10est faux dès le départ ;kvaut 10. C'est le cas où unTantQuene s'exécute jamais.
Tu avais trouvé ?
Exercice 3 sur 8 Somme et moyenne avec sentinelle Réussi À revoir
Écris un programme qui lit des montants de frais un par un. La saisie de 0 signale la fin (c'est une valeur sentinelle, qui n'est pas un frais). Le programme affiche le nombre de frais, leur total et leur moyenne. Que se passe-t-il si l'on saisit 0 tout de suite ?
Voir la réponseMasquer la réponse de l'exercice 3
On ne connaît pas le nombre de saisies : c'est un TantQue, avec une première saisie avant la boucle.
nb = 0
total = 0.0
montant = float(input("Montant (0 pour finir) ? "))
while montant != 0:
nb = nb + 1
total = total + montant
montant = float(input("Montant (0 pour finir) ? "))
if nb > 0:
print(nb, "frais, total", total, "- moyenne", round(total / nb, 2))
else:
print("Aucun frais saisi")
Avec 0 tout de suite, la boucle ne s'exécute pas, nb vaut 0 et le programme affiche « Aucun frais saisi ». Sans le test if nb > 0, la division total / nb lèverait ZeroDivisionError. Comparer un réel à 0 avec != est sans risque ici : 0 est saisi tel quel, il n'est pas le résultat d'un calcul.
Tu avais trouvé ?
Exercice 4 sur 8 Nombre de chiffres Réussi À revoir
Écris un algorithme qui compte les chiffres d'un entier positif, en le divisant par 10 jusqu'à ce qu'il soit nul. Fais la trace pour 40597. Quel est le résultat pour 0, et comment le corriger ?
Voir la réponseMasquer la réponse de l'exercice 4
nb ← 0
TantQue n > 0 Faire
n ← n DIV 10
nb ← nb + 1
FinTantQue
Afficher(nb)
| Tour | n | nb |
|---|---|---|
| avant | 40597 | 0 |
| 1 | 4059 | 1 |
| 2 | 405 | 2 |
| 3 | 40 | 3 |
| 4 | 4 | 4 |
| 5 | 0 | 5 |
Résultat : 5 chiffres. Pour 0, la boucle ne s'exécute pas et l'algorithme affiche 0, alors que 0 s'écrit avec un chiffre. Une boucle Répéter corrige le problème, car elle fait au moins un tour :
n = 0
nb = 0
while True:
n = n // 10
nb = nb + 1
if n == 0:
break
print(nb)
Tu avais trouvé ?
Exercice 5 sur 8 Devine le nombre Réussi À revoir
Le programme tire un entier au hasard entre 1 et 100. L'utilisateur propose des nombres ; le programme répond « plus grand » ou « plus petit » jusqu'à ce qu'il trouve, puis affiche le nombre d'essais. Écris-le en Python.
Voir la réponseMasquer la réponse de l'exercice 5
import random
secret = random.randint(1, 100)
essais = 0
while True:
proposition = int(input("Ton nombre ? "))
essais = essais + 1
if proposition < secret:
print("plus grand")
elif proposition > secret:
print("plus petit")
else:
break
print("Trouvé en", essais, "essais")
C'est un Répéter : il faut au moins une proposition. En coupant l'intervalle en deux à chaque essai (proposer 50, puis 25 ou 75…), on trouve toujours en 7 essais au plus. C'est l'idée de la recherche dichotomique.
Tu avais trouvé ?
Exercice 6 sur 8 Suite de Fibonacci Réussi À revoir
La suite de Fibonacci commence par 0 et 1, et chaque terme est la somme des deux précédents. Écris un programme qui affiche les 10 premiers termes.
Voir la réponseMasquer la réponse de l'exercice 6
On garde les deux derniers termes dans deux variables, et on les fait avancer à chaque tour.
a = 0
b = 1
for i in range(10):
print(a, end=" ")
suivant = a + b
a = b
b = suivant
print()
0 1 1 2 3 5 8 13 21 34
Les trois affectations reprennent la technique de l'échange de variables : suivant évite d'écraser a trop tôt. En Python, a, b = b, a + b fait la même chose en une ligne.
Tu avais trouvé ?
Exercice 7 sur 8 Triangle de nombres Réussi À revoir
Écris un programme qui, pour n = 4, affiche le triangle ci-dessous, avec deux boucles for imbriquées. Combien de fois le print interne s'exécute-t-il pour n quelconque ?
1
1 2
1 2 3
1 2 3 4
Voir la réponseMasquer la réponse de l'exercice 7
n = 4
for i in range(1, n + 1):
for j in range(1, i + 1):
print(j, end=" ")
print()
La boucle interne fait i tours au tour i, soit 1 + 2 + … + n = n(n + 1)/2 affichages de nombres : 10 pour n = 4. Le print() vide, dans la boucle externe, passe à la ligne.
Tu avais trouvé ?
Exercice 8 sur 8 Suite de Syracuse Réussi À revoir
On part d'un entier n > 0. S'il est pair, on le divise par 2 ; sinon, on le remplace par 3n + 1. On recommence jusqu'à obtenir 1. Écris un programme qui affiche le nombre d'étapes pour un n saisi. Combien pour 6 ? pour 7 ?
Voir la réponseMasquer la réponse de l'exercice 8
n = int(input("n ? "))
etapes = 0
while n != 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
etapes = etapes + 1
print(etapes, "étapes")
Pour 6 : 6, 3, 10, 5, 16, 8, 4, 2, 1, soit 8 étapes. Pour 7 : 16 étapes. Personne n'a jamais démontré que cette boucle s'arrête pour tout n (c'est la conjecture de Syracuse), même si on l'a vérifié pour d'immenses quantités de nombres : un bel exemple de boucle dont la finitude n'est pas évidente.
Tu avais trouvé ?