Maths Seconde, programme français • Exercices corrigés à Montréal

Fiche de révision : algorithmique et Python (Seconde)

Cette fiche ne refait pas le cours de Python : vous l'avez déjà dans votre classeur. Elle traite ce que le cours ne dit jamais et qui décide pourtant de la note, l'erreur exacte qui coûte deux points sur une copie, la boucle à choisir selon l'énoncé, et la manière de retrouver une erreur à partir de ce que le programme affiche.

Elle est écrite pour les élèves de Seconde du programme français à Montréal, en particulier au Lycée Marie de France et au Collège Stanislas. Une fois la fiche lue, la série d'exercices corrigés du même chapitre met chaque réflexe à l'épreuve.

Le fil du chapitre

L'ordinateur ne fait pas ce que vous voulez, il fait ce que vous écrivez. Toutes les erreurs de ce chapitre viennent d'une ligne parfaitement valide qui ne dit pas ce que l'élève croyait : la borne de droite de range qui est exclue, le print qui remplace le return, l'initialisation glissée à l'intérieur de la boucle. Un programme faux ne signale rien, il donne simplement un mauvais nombre, et c'est pour cela qu'il faut savoir le tracer à la main.

Ce chapitre fait partie de Mathématiques en Seconde

Avant ce chapitre

Cette fiche suppose ces notions acquises. Si une méthode ci-dessous reste opaque, c'est presque toujours l'une d'elles qui manque, pas la fiche.

Remonter plus loin : la chaîne complète (4 chapitres) ↓

Le chemin de remédiation, du plus ancien au plus proche. Un élève qui reprend ce chapitre de zéro le reprend dans cet ordre.

  1. 1Algorithmique et ScratchSixième
  2. 2Algorithmique et ScratchCinquième
  3. 3Algorithmique et ScratchQuatrième
  4. 4Algorithmique et ScratchTroisième

L'essentiel

Ce que fait exactement une affectation

  • L'instruction x = 3 range la valeur 33 dans la variable x. Elle se lit de DROITE À GAUCHE : on calcule d'abord, on range ensuite.
  • C'est pourquoi x = x + 1 est parfaitement licite : la machine calcule l'ancien x plus un, puis écrase l'ancienne valeur.
  • Un seul signe égal AFFECTE, deux signes égal TESTENT. Le test renvoie True ou False, l'affectation ne renvoie rien.
  • Une variable non initialisée n'existe pas : toute variable utilisée dans une boucle doit avoir reçu une valeur AVANT la boucle.
  • Les noms comptent : x et X sont deux variables différentes, et Python distingue les majuscules des minuscules partout.

Une trace d'exécution se fait dans un tableau à une colonne par variable et une ligne par tour de boucle. C'est le seul moyen fiable de comprendre un programme qu'on n'a pas écrit, et c'est une question de contrôle à part entière.

Les deux boucles, et ce qui les sépare

  • for k in range(a, b) parcourt les entiers de a à b moins un : la borne de DROITE est exclue, toujours.
  • range(n) part de 00 et s'arrête à n moins un, donc il fait exactement n tours. range(a, b, p) avance de p en p.
  • On utilise for quand le nombre de tours est connu à l'avance, et while quand il dépend d'une condition, typiquement une recherche de seuil.
  • La condition d'un while est une condition de CONTINUATION, pas d'arrêt : la boucle tourne tant qu'elle est vraie.
  • Dans un while, quelque chose doit changer à chaque tour, sinon la boucle est infinie et le programme ne rend jamais la main.

Compter les tours d'une boucle for : range(a, b) en fait exactement b moins a. Pour range(1, 10), cela fait neuf tours et non dix, et c'est l'erreur la plus fréquente du chapitre.

Fonctions, listes et nombres décimaux

  • return RENVOIE une valeur exploitable par le reste du programme ; print se contente d'AFFICHER à l'écran.
  • Une fonction sans return renvoie None : écrire deux fois le résultat d'une telle fonction provoque une erreur.
  • return interrompt immédiatement la fonction : placé dans une boucle, il fait sortir dès le premier tour.
  • Pour une liste L : len(L) donne son nombre d'éléments, L[0] est le premier et L[len(L) - 1] le dernier. L[len(L)] n'existe pas.
  • Les nombres décimaux sont approchés en machine : on ne teste jamais l'égalité de deux flottants, on compare la valeur absolue de leur différence à un petit nombre.

En Seconde, une fonction demandée par un énoncé se termine presque toujours par return, jamais par print. C'est la première chose que le correcteur regarde.

Les pièges qui coûtent des points

Les erreurs ci-dessous sont celles que je corrige le plus souvent en séance. Chacune coûte des points sur une copie, même quand le raisonnement est juste.

1. Croire que la borne de droite de range est incluse

toute la question, et un résultat presque juste qui échappe à la relecture

Ce qu'il ne faut pas écrire

« for k in range(1, 10) parcourt les entiers de 11 à 1010, donc la somme obtenue est 5555. »

Ce qu'il faut écrire

« range(1, 10) parcourt 11, 22, ..., 99 : la borne de droite est EXCLUE, donc la somme vaut 4545. Pour aller jusqu'à 1010, il faut écrire range(1, 11). »

01234567891011range(1, 10)10 exclu
Les points pleins sont les entiers réellement parcourus : la borne de droite 1010 est un point vide, elle n'est jamais atteinte. La somme vaut donc 4545 et non 5555.

Pourquoi : La convention vient du fait que range(n) commence à zéro et fait exactement n tours. Le contrôle : le nombre de tours de range(a, b) vaut b moins a, ici neuf. Un test rapide dans la console affiche la liste et tranche en une seconde.

2. Utiliser un seul signe égal dans un test

le programme ne s'exécute pas du tout, donc toute la question

Ce qu'il ne faut pas écrire

« if x = 0 : print('nul') »

Ce qu'il faut écrire

« if x == 0 : print('nul') : un seul signe égal AFFECTE une valeur, deux signes égal TESTENT une égalité. »

Pourquoi : Python refuse cette ligne avec une erreur de syntaxe, ce qui est une chance : l'erreur est immédiate et localisée. Le moyen de ne plus l'oublier : une affectation range quelque chose, un test pose une question, et une question demande deux signes.

3. Écrire print au lieu de return dans une fonction

1 à 2 points, et un blocage sur toutes les questions qui réutilisent la fonction

Ce qu'il ne faut pas écrire

« def carre(x) : print(x * x) puis y = 2 * carre(3) »

Ce qu'il faut écrire

« def carre(x) : return x * x puis y = 2 * carre(3), qui vaut 1818. Une fonction sans return renvoie None, et deux fois None est une erreur. »

Pourquoi : print envoie du texte à l'écran, il ne rend aucune valeur au programme. Le test qui tranche : si le résultat de la fonction doit être réutilisé dans un calcul, il faut return. En Seconde, c'est presque toujours le cas.

4. Initialiser une variable à l'intérieur de la boucle

toute la question, et le programme rend le dernier terme au lieu de la somme

Ce qu'il ne faut pas écrire

« for k in range(1, 5) : s = 0 ; s = s + k puis return s, qui rend 44. »

Ce qu'il faut écrire

« s = 0 se place AVANT la boucle. Ensuite, for k in range(1, 5) : s = s + k accumule bien, et la fonction rend 1010. »

s = 1s = 2s = 3s = 4s = 1s = 3s = 6s = 10tour 1tour 2tour 3tour 4s = 0 DANS la boucles = 0 AVANT la bouclerend 4rend 10
À chaque tour, l'initialisation efface ce qui précède : la valeur rendue est celle du DERNIER tour, 44, au lieu du cumul 1010. Le symptôme est reconnaissable à l'oeil.

Pourquoi : Placée dans la boucle, l'initialisation efface le total à chaque tour : il ne reste que le dernier ajout. La signature de cette erreur est reconnaissable, le résultat est toujours égal au dernier élément traité.

5. Écrire un while dont la condition ne peut jamais devenir fausse

le programme ne rend jamais de résultat, donc toute la question

Ce qu'il ne faut pas écrire

« n = 0 ; while n < 10 : print(n) »

Ce qu'il faut écrire

« n = 0 ; while n < 10 : print(n) ; n = n + 1 : sans la mise à jour de n, la condition reste vraie et la boucle est infinie. »

Pourquoi : Le while ne modifie rien tout seul, il ne fait que relire la condition. Avant d'écrire la moindre ligne d'un while, se demander quelle variable de la condition va changer, et vérifier qu'elle est bien modifiée dans le corps de la boucle.

6. Utiliser la longueur de la liste comme indice

le programme s'arrête sur une erreur, donc toute la question

Ce qu'il ne faut pas écrire

« Le dernier élément de L est L[len(L)]. »

Ce qu'il faut écrire

« Les indices vont de 00 à len(L) moins un, donc le dernier élément est L[len(L) - 1]. Pour une liste de cinq éléments, c'est L[4]. »

127942101234?5len(L) = 5, dernier indice 4L[5] n'existe pas
Cinq cases, mais des indices qui vont de 00 à 44 : la case d'indice 55 est dessinée en pointillés parce qu'elle n'existe pas. C'est elle que réclame L[len(L)].

Pourquoi : Les indices commencent à zéro, donc le dernier est décalé de un par rapport à la longueur. Le message d'erreur, list index out of range, désigne exactement cette situation et permet de la corriger sans relire tout le programme.

7. Tester l'égalité de deux nombres décimaux

toute la question, et un programme de balayage qui ne s'arrête jamais

Ce qu'il ne faut pas écrire

« if 0.1 + 0.2 == 0.3 : print('égal') affiche égal. »

Ce qu'il faut écrire

« En machine, 0,1+0,20{,}1+0{,}2 vaut 0,300000000000000040{,}30000000000000004 : le test est FAUX. On écrit if abs(0.1 + 0.2 - 0.3) < 1e-9 pour comparer des décimaux. »

Pourquoi : Les nombres décimaux sont stockés de façon approchée en binaire, comme un tiers l'est en écriture décimale. La conséquence pratique : dans un balayage, on boucle sur des ENTIERS puis on divise, au lieu d'additionner des dixièmes.

8. Placer le return à l'intérieur de la boucle

toute la question, et le résultat correspond au premier tour seulement

Ce qu'il ne faut pas écrire

« for k in range(1, 5) : s = s + k ; return s renvoie 11. »

Ce qu'il faut écrire

« Le return se place APRÈS la boucle, à l'indentation de la fonction et non à celle du corps de la boucle : la fonction renvoie alors 1010. »

Pourquoi : return sort immédiatement de la fonction, donc placé dans la boucle il l'interrompt au premier passage. En Python, l'indentation N'EST PAS de la mise en page : c'est elle qui dit ce qui est dans la boucle et ce qui est en dehors.

Quelle méthode choisir

Boucle for ou boucle while ?

Se demander si le nombre de tours est connu AVANT de lancer le programme.

  • Si l'énoncé dit « pour les 2020 premiers termes », « de 11 à nn », « pour chaque élément » boucle FOR, avec un range dont on vérifie les deux bornes

    Exemple : for k in range(1, 21) fait vingt tours

  • Si l'énoncé dit « jusqu'à ce que », « tant que », « à partir de quand », « le plus petit entier tel que » boucle WHILE, avec un compteur mis à jour dans le corps

    Exemple : while p <= 20000 : p = p * 1.12 ; n = n + 1

  • Si il faut parcourir une liste et n'utiliser que les valeurs for x in L, sans indice

    Exemple : for x in L : s = s + x

  • Si il faut parcourir une liste et connaître la POSITION de chaque élément for i in range(len(L)), puis L[i]

    Exemple : for i in range(len(L)) : print(i, L[i])

    range(len(L)) va de 00 à len(L) moins un, exactement les indices valides

  • Si il faut balayer des valeurs décimales boucler sur des ENTIERS puis diviser, jamais additionner des dixièmes

    Exemple : for k in range(0, 21) : x = k/10

Toute boucle while doit contenir la ligne qui fait progresser la condition. Si on ne peut pas nommer cette ligne, la boucle est infinie.

Du symptôme à l'erreur : diagnostiquer un programme faux

Regarder ce que le programme affiche, ou l'erreur qu'il produit.

  • Si le programme affiche None il manque un return : la fonction se termine sans renvoyer de valeur

    Exemple : def carre(x) : print(x * x)

  • Si le résultat est égal au DERNIER élément traité l'initialisation est à l'intérieur de la boucle et efface l'accumulation à chaque tour

    Exemple : s = 0 écrit sous le for au lieu d'être au-dessus

  • Si le résultat correspond au PREMIER tour seulement le return est indenté dans la boucle et la coupe au premier passage

    Exemple : return s aligné avec s = s + k

  • Si il manque exactement un terme ou un tour borne de droite du range, qui est exclue

    Exemple : range(1, 10) au lieu de range(1, 11)

  • Si le message dit list index out of range un indice vaut len(L) alors que le dernier valide est len(L) moins un

    Exemple : L[len(L)] au lieu de L[len(L) - 1]

  • Si le programme ne s'arrête pas aucune variable de la condition du while n'est modifiée dans le corps de la boucle

    Exemple : while n < 10 sans n = n + 1

Devant un programme qu'on ne comprend pas, la trace d'exécution à la main sur trois tours est plus rapide que la relecture. Un tableau, une colonne par variable, une ligne par tour.

La rédaction attendue

Le correcteur coche des étapes. Les voici dans l'ordre, avec la phrase de conclusion qu'il attend mot pour mot.

Écrire une fonction de recherche de seuil

Quand l'utiliser : Dès que l'énoncé demande « à partir de quand », « au bout de combien d'années », « le plus petit entier tel que ».

  1. 1 Repérer la grandeur qui évolue et la grandeur qui compte les tours : ce sont les deux variables de la fonction.
  2. 2 Initialiser les DEUX variables avant la boucle, avec les valeurs de départ de l'énoncé.
  3. 3 Écrire la condition de CONTINUATION du while, c'est-à-dire la négation du seuil à atteindre : on boucle tant que le seuil n'est pas franchi.
  4. 4 Dans le corps, mettre à jour la grandeur ET le compteur. Oublier le compteur donne une boucle infinie.
  5. 5 Placer le return APRÈS la boucle, à l'indentation de la fonction, puis conclure par une phrase en français avec l'unité.

Phrase de conclusion

« La fonction renvoie 1313 : la population dépasse 2000020\,000 bactéries au bout de 1313 heures. »

Le piège : Écrire la condition d'arrêt au lieu de la condition de continuation, ce qui donne une boucle qui ne démarre jamais et une fonction qui renvoie zéro.

Barème : Souvent 1 point pour les initialisations, 1 point pour la condition du while, 1 point pour les deux mises à jour, 1 point pour le return bien placé et la phrase.

Faire une trace d'exécution

Quand l'utiliser : Dès que l'énoncé demande ce qu'affiche un programme, ou la valeur d'une variable à la fin.

  1. 1 Dessiner un tableau avec une colonne par variable, plus une colonne pour le numéro de tour.
  2. 2 Remplir la ligne zéro avec les valeurs d'initialisation, avant l'entrée dans la boucle.
  3. 3 Pour chaque tour, recopier les valeurs inchangées et calculer les nouvelles, dans l'ordre exact des lignes du programme.
  4. 4 Vérifier la condition de la boucle À CHAQUE ligne du tableau, et s'arrêter dès qu'elle devient fausse.
  5. 5 Lire la dernière ligne pour répondre, et préciser quelle variable est renvoyée ou affichée.

Phrase de conclusion

« Après le troisième tour, s vaut 66 et k vaut 44 ; la condition k inférieur à 44 est alors fausse, donc la boucle s'arrête et la fonction renvoie 66. »

Le piège : Mettre à jour toutes les variables en même temps. Les lignes s'exécutent dans l'ordre où elles sont écrites, et une variable modifiée en première ligne sert déjà avec sa nouvelle valeur en deuxième ligne.

Vérifier avant de rendre

Cinq minutes de vérification récupèrent plus de points qu'un exercice de plus commencé à la hâte.

L'exercice type décortiqué

Une recherche de seuil, écrite puis vérifiée

Une culture contient 50005\,000 bactéries et leur nombre augmente de 12 %12\ \% par heure.

1. Écrire une fonction Python sans paramètre qui renvoie le nombre d'heures au bout duquel la population dépasse strictement 2000020\,000 bactéries.

2. Justifier le résultat par un calcul direct.

python
def seuil():
    p = 5000
    n = 0
    while p <= 20000:
        p = p * 1.12
        n = n + 1
    return n

Étape 1

Le nombre de tours n'est pas connu à l'avance, puisque c'est précisément ce que l'on cherche : on choisit donc une boucle while et non une boucle for.

Pourquoi

Ce choix se justifie en une phrase sur la copie, et il est noté. Une boucle for exigerait de connaître le résultat avant de le calculer, ce qui est impossible ici.

Étape 2

On initialise les deux variables AVANT la boucle : p vaut 50005\,000, la population de départ, et n vaut 00, le nombre d'heures écoulées.

Pourquoi

Deux variables évoluent, il faut donc deux initialisations. Placer l'une des deux dans la boucle la remettrait à zéro à chaque tour, et le programme ne rendrait jamais autre chose que 11.

Étape 3

La condition est while p <= 20000 : on continue TANT QUE le seuil n'est pas dépassé. Le seuil est strict, donc l'inégalité de continuation est large.

Pourquoi

Une condition de while est une condition de continuation, jamais d'arrêt. Écrire while p > 20000 ferait sortir immédiatement et la fonction renverrait 00, un résultat faux mais parfaitement silencieux.

Étape 4

Dans le corps, on met à jour les deux variables : p = p * 1.12 applique la hausse de douze pour cent, et n = n + 1 compte l'heure écoulée.

Pourquoi

L'oubli de n = n + 1 donne une boucle infinie, puisque rien ne ferait alors avancer le compteur. L'oubli de la mise à jour de p en donne une autre, car la condition resterait vraie éternellement.

Étape 5

Le return n est placé après la boucle, à l'indentation de la fonction. Indenté d'un cran de plus, il sortirait dès le premier tour et rendrait 11.

Pourquoi

En Python, l'indentation détermine ce qui est dans la boucle. C'est le seul langage du programme où un décalage de quatre espaces change complètement le sens, et c'est le point que les correcteurs vérifient en premier.

Étape 6

Trace des premiers tours : après le premier, p vaut 56005\,600 et n vaut 11 ; après le deuxième, p vaut 62726\,272 et n vaut 22. La population croît bien, et le compteur suit.

Pourquoi

Trois lignes de trace suffisent à valider la structure de la boucle sans exécuter le programme. C'est aussi la forme exacte sous laquelle la question peut être posée au contrôle.

Étape 7

Vérification directe : 5000×1,1212194805\,000\times 1{,}12^{12}\approx 19\,480, qui ne dépasse pas 2000020\,000, tandis que 5000×1,1213218185\,000\times 1{,}12^{13}\approx 21\,818, qui le dépasse. La fonction renvoie donc bien 1313.

Pourquoi

Le calcul direct est indépendant du programme : il valide le résultat sans refaire le raisonnement algorithmique. Tester les deux rangs encadrants, et pas seulement le bon, prouve que le seuil trouvé est le plus petit possible.

Conclusion rédigée

La fonction renvoie 1313 : la population de bactéries dépasse 2000020\,000 au bout de 1313 heures.

L'erreur classique sur cet exercice : Écrire while p < 20000 au lieu de while p <= 20000. Ici les deux versions donnent le même résultat, mais si la population valait exactement 2000020\,000 à un tour, la première sortirait trop tôt. Le sens de l'inégalité doit toujours recopier celui de l'énoncé.

À savoir par cœur

  • Une affectation se lit de droite à gauche : x = x + 1 calcule d'abord, range ensuite.
  • Un signe égal AFFECTE, deux signes égal TESTENT.
  • range(a, b) parcourt a jusqu'à b moins un et fait exactement b moins a tours : la borne de droite est exclue.
  • for quand le nombre de tours est connu, while quand il dépend d'une condition. La condition du while est une condition de continuation.
  • Toute variable accumulée s'initialise AVANT la boucle, et le return se place APRÈS.
  • return renvoie, print affiche. Une fonction sans return renvoie None.
  • Les indices d'une liste vont de 00 à len(L) moins un : le dernier élément est L[len(L) - 1].
  • On ne teste jamais l'égalité de deux décimaux : on compare la valeur absolue de leur différence à un petit nombre.

Questions fréquentes

Pourquoi range de 1 à 10 ne va que jusqu'à 9 en Python ?

Parce que la borne de droite est exclue par convention. Cette convention vient du fait que range avec un seul argument commence à zéro et fait exactement autant de tours que le nombre donné. Retenez la règle du nombre de tours : range de a à b en fait b moins a. Pour aller jusqu'à dix, il faut écrire range de un à onze.

Quelle différence entre print et return dans une fonction ?

Print affiche du texte à l'écran mais ne rend aucune valeur au programme, alors que return renvoie une valeur réutilisable dans un calcul. Une fonction sans return renvoie None, et toute opération sur None provoque une erreur. Dès que le résultat doit servir ailleurs, il faut return, ce qui est presque toujours le cas en Seconde.

Comment savoir s'il faut une boucle for ou une boucle while ?

On regarde si le nombre de tours est connu avant de lancer le programme. S'il est fixé par l'énoncé, comme pour les vingt premiers termes, c'est une boucle for. S'il dépend d'un résultat, comme dans à partir de quelle année la population dépasse un seuil, c'est une boucle while avec un compteur mis à jour à chaque tour.

Pourquoi mon programme renvoie le dernier nombre au lieu de la somme ?

Parce que la variable qui accumule est initialisée à zéro à l'intérieur de la boucle et non avant. À chaque tour, le total est effacé puis remplacé par le seul terme courant, donc il ne reste que le dernier. Il suffit de remonter la ligne d'initialisation au-dessus de la boucle, à l'indentation de la fonction.

Pourquoi zéro virgule un plus zéro virgule deux ne vaut pas zéro virgule trois en Python ?

Parce que les nombres décimaux sont stockés de façon approchée en binaire, exactement comme un tiers ne s'écrit pas exactement en décimal. Le résultat affiché comporte donc de minuscules décimales parasites. On ne teste jamais l'égalité de deux décimaux : on vérifie que la valeur absolue de leur différence est plus petite qu'un très petit nombre.

Passer à la pratique

Exercices corrigés : Algorithmique et Python

Une méthode se prouve sur une copie, pas sur une fiche. La série du même chapitre reprend chacun de ces pièges dans un exercice, avec le corrigé rédigé étape par étape.

  • 15 exercices corrigés
  • 150 points
  • 225 minutes
Faire les exercices
Fiche précédente Les statistiques descriptives Fiche suivante Python appliqué aux sciences

Ce chapitre resservira dans

Les chapitres qui le réclament en amont, plus tard dans l'année ou dans les années suivantes.

Voir aussi

Vous cherchez un tuteur de maths et de Python en Seconde à Montréal ?

Contactez-moi pour une première séance. On reprend les gestes de l'algorithmique qui coûtent des points, de la trace d'exécution jusqu'à la recherche de seuil, puis on les met à l'épreuve sur des exercices du niveau réel des contrôles au Lycée Marie de France et au Collège Stanislas.

Site par Studio Squalli