Maths Seconde, programme français • Exercices corrigés à Montréal
Exercices corrigés : algorithmique et programmation Python (Seconde)
Voici une série d'exercices corrigés d'algorithmique et de programmation Python, au niveau de la classe de Seconde du programme français. Elle couvre les variables et l'affectation, les instructions conditionnelles, les boucles for et while, les fonctions en Python, la simulation aléatoire et la résolution d'une équation par dichotomie, en quinze exercices répartis en trois parties. Elle se sert aussi des listes, des nombres premiers et de l'algorithme d'Euclide comme terrains d'entraînement : le programme de Seconde ne les exige pas, et la page le dit là où ils servent.
À la fin de la série, vous savez dresser la trace d'exécution d'un programme à la main (exercice 1), ordonner les tests d'une suite de if, elif et else (exercice 2), choisir entre une boucle bornée et une boucle while pour une recherche de seuil (exercices 3, 4 et 7), écrire une fonction qui renvoie une valeur avec return (exercice 5), parcourir une liste pour compter ou chercher un maximum (exercice 6), calculer un PGCD par l'algorithme d'Euclide (exercice 13) et encadrer une solution par balayage puis par dichotomie (exercices 10 et 15).
Les situations sont concrètes : une culture de bactéries qui croît de 8 % par heure, un capital placé qui doit dépasser 3 000 dollars, des lancers de dé simulés avec randint, un tarif de taxi programmé par morceaux, les diviseurs et les nombres premiers.
En Seconde, l'algorithmique n'est pas un cours d'informatique : c'est un outil de mathématiques. Chaque programme de cette série calcule quelque chose qui figure ailleurs au programme, un seuil, une moyenne, une fréquence, une valeur approchée. Les corrigés traitent les pièges qui coûtent des points : un test placé trop tôt qui masque les suivants (exercice 2), print confondu avec return (exercices 5 et 9), un maximum initialisé à 0 (exercice 6), une boucle while qui ne s'arrête jamais (exercice 9), et l'exercice 10 montre pourquoi une boucle qui ajoute 0,1 finit par mentir.
Série autocorrigéeTape tes réponses et vérifie-les question par question : la page te dit juste ou faux avant d'ouvrir la correction. Avec un compte, chaque bonne réponse du premier coup rapporte des points, et tes réponses justes restent remplies quand tu reviens.
•Une affectation x = 3 range une valeur dans une variable. Elle se lit de droite à gauche, et x = x + 1 est parfaitement licite : on calcule d'abord, on range ensuite.
•= affecte une valeur, == teste une égalité. Écrire = dans un test produit une erreur de syntaxe ; écrire == à la place d'une affectation ne produit aucune erreur, mais ne modifie rien.
•for k in range(a, b) parcourt les entiers de a à b - 1 : la borne de droite est exclue. range(a, b, p) avance de p en p.
•On utilise une boucle for quand le nombre de tours est connu à l'avance, et une boucle while quand il dépend d'une condition, typiquement une recherche de seuil.
•Dans une boucle while, il faut que quelque chose change à chaque tour, sinon la boucle est infinie.
•return renvoie une valeur exploitable ; print se contente d'afficher. Une fonction sans return renvoie None.
•Pour une liste L : len(L) donne son nombre d'éléments, L[0] est le premier et L[len(L) - 1] le dernier. Le programme de Seconde précise « Aucune connaissance sur les listes n'est exigée » : elles sont au programme de Première, et l'exercice 6 s'en sert comme d'un outil.
•L'écriture des nombres décimaux en machine est approchée : on n'additionne pas 0,1 des dizaines de fois si l'on veut un résultat exact.
Partie A : Les bases (/50)
Exercice 1 : Variables et trace d'exécution
On considère le programme suivant. Répondez sans machine : savoir suivre une exécution à la main est exactement ce qui est évalué.
Le tableau ci-dessous donne la forme attendue à la question a) : il reste à le remplir.
a = 5
b = 3
a = a + b
b = a - b
a = a - b
print(a, b)
a) Dressez le tableau des valeurs successives de a et de b, ligne par ligne, et donnez ce qui est affiché.
b) Que réalise ce programme, quelles que soient les valeurs initiales ?
c) Écrivez le programme qui réalise la même chose en utilisant une troisième variable.
d) Que va afficher le programme suivant : x = 7, puis y = x, puis x = 10, puis print(y) ? Expliquez.
Voir la correction
Réponses
a)a : 5, 8, 8, 3 ; b : 3, 3, 5, 5 ; affiche 3 5
b)Il échange a et b
c)c = a, a = b, b = c
d)Affiche 7
a)
On suit l'exécution LIGNE PAR LIGNE, en notant après chaque instruction la valeur de chaque variable. Après les deux premières lignes, a vaut 5 et b vaut 3. La ligne a = a + b donne a=8, b restant à 3. La ligne b = a - b utilise le NOUVEAU a : b=8−3=5, a restant à 8. La ligne a = a - b utilise le nouveau b : a=8−5=3. Le programme affiche donc 3 5.
b)
Il ÉCHANGE le contenu des deux variables, sans utiliser de variable supplémentaire. On est parti de a=5 et b=3, on arrive à a=3 et b=5. Le mécanisme est général : la somme a+b est stockée dans a et sert de mémoire temporaire, dont on extrait successivement l'ancien a puis l'ancien b.
c)
Avec une variable auxiliaire, on écrit c = a puis a = b puis b = c. C'est la version que l'on écrit en pratique, pour deux raisons : elle se lit immédiatement, et elle fonctionne avec n'importe quel type de données, alors que la version de l'énoncé n'a de sens que pour des NOMBRES. On ne peut pas additionner deux chaînes de caractères et espérer les séparer ensuite.
d)
Il affiche 7. Au moment de l'affectation y = x, Python range dans y la VALEUR que x contient alors, c'est-à-dire 7. Modifier x ensuite ne modifie pas y : une affectation copie une valeur à l'instant où elle s'exécute, elle ne crée aucun lien permanent entre les deux variables.
Les questions a) et d) portent sur le même point, et c'est le plus important du chapitre : le signe = de Python n'est PAS l'égalité mathématique, c'est une AFFECTATION. En mathématiques, écrire a=a+b serait absurde et forcerait b à être nul ; en Python cela signifie calculer a+b avec les valeurs actuelles, puis ranger le résultat dans a, en écrasant l'ancienne valeur. Une affectation se lit donc toujours de DROITE à GAUCHE, et le seul moyen fiable de suivre un programme est de tenir un tableau des valeurs successives, comme en a). C'est exactement ce que l'épreuve évalue, et c'est aussi ce qui permet de repérer une erreur sans machine.
c = a
a = b
b = c
Coche ici les exercices faits ou à revoir : un compte gratuit, sans mot de passe, retient tes coches et tes réponses justes d'une visite à l'autre, te dit quel chapitre attaquer ensuite et te permet de demander l'exercice qui te manque. Crée ton espace, un courriel suffit.
Exercice 2 : Instructions conditionnelles
On considère la fonction suivante, qui attribue une mention à une note sur 20.
d)Équivaut à note >= 16 ; intention : note >= 14 and note < 16
a)
mention(14) renvoie 'Bien' : 14 n'est pas supérieur ou égal à 16, le premier test échoue, mais il l'est à 14 et le second réussit. mention(11.5) renvoie 'Pas de mention', aucun test n'étant satisfait. mention(16) renvoie 'Tres bien', car le test utilise une inégalité LARGE et 16≥16. mention(20) renvoie également 'Tres bien'.
b)
Tous les tests suivants deviendraient INACCESSIBLES pour les notes élevées : une note de 18 vérifie déjà note >= 12, donc la fonction renverrait 'Assez bien' et s'arrêterait là, sans jamais examiner les autres branches. Dans une cascade de elif, il faut ordonner les tests du plus RESTRICTIF au plus large, car le premier qui réussit met fin à la cascade.
c)
Il suffit d'insérer un test supplémentaire avant le else final : on ajoute elif note >= 10: renvoyant 'Pas de mention', et le else renvoie alors 'Refuse'. L'ordre décroissant est conservé, 10 venant après 12 dans la cascade.
d)
La condition équivaut à note >= 16 tout court : si une note est supérieure ou égale à 16, elle est AUTOMATIQUEMENT supérieure ou égale à 14, donc le second test n'apporte rien. L'élève voulait sans doute exprimer un INTERVALLE, ce qui s'écrit note >= 14 and note < 16, avec deux bornes différentes et surtout un test strict d'un côté.
Une cascade de elif fonctionne comme un filtre en escalier : chaque valeur descend jusqu'au premier test qu'elle satisfait, et s'y arrête. C'est ce qui rend l'ORDRE décisif, et c'est aussi ce qui permet d'écrire elif note >= 14 sans préciser and note < 16 : à ce stade, les notes supérieures à 16 ont déjà été interceptées. Ici, chaque branche se termine par return, qui quitte la fonction : des if indépendants donneraient donc les mêmes résultats. En revanche, si chaque branche affectait une variable (m = 'Bien', ...) au lieu de renvoyer, tous les if seraient évalués et la dernière affectation l'emporterait : mention(18) donnerait 'Assez bien'. On retiendra enfin la différence entre le test large ≥ et le test strict >, qui décide du sort exact des valeurs frontières comme 16 en a).
On rappelle que range(a, b) parcourt les entiers de a jusqu'à b - 1 inclus : la borne de droite est exclue.
s = 0
for k in range(1, 11):
s = s + k
print(s)
a) Que calcule ce programme ? Donnez la valeur affichée.
b) Modifiez-le pour qu'il calcule la somme des carrés des entiers de 1 à 10, et donnez le résultat.
c) Quelles valeurs prend k dans for k in range(0, 20, 5) ?
d) Un second programme initialise p à 1 puis, pour k allant de 1 à 5, effectue p = p * k. Que calcule-t-il et que vaut p à la fin ?
Voir la correction
Réponses
a)Somme de 1 à 10 : 55
b)s = s + k*k : 385
c)0, 5, 10, 15
d)5!=120
a)
Il calcule la SOMME des entiers de 1 à 10, puisque range(1, 11) parcourt 1, 2, jusqu'à 10, la borne 11 étant exclue. La valeur affichée est 55, ce que confirme la formule 210×11=55. Écrire range(1, 10) donnerait 45 : oublier que la borne de droite est exclue est l'erreur la plus fréquente du chapitre.
b)
Il suffit de remplacer la ligne du corps par s = s + k*k, la structure de la boucle restant identique. Le résultat est 1+4+9+16+25+36+49+64+81+100=385.
c)
La variable k prend les valeurs 0, 5, 10 et 15. Le TROISIÈME argument est le pas ; la valeur 20 est exclue, exactement comme dans range(a, b). Il y a donc quatre valeurs et non cinq, et l'on notera que 15+5=20 tombe précisément sur la borne exclue.
d)
Il calcule le PRODUIT des entiers de 1 à 5, c'est-à-dire la factorielle de 5. À la fin, p vaut 1×2×3×4×5=120. Le point important est l'INITIALISATION : il faut partir de 1 et non de 0, sinon tous les produits successifs seraient nuls et le résultat vaudrait 0. L'élément neutre de la multiplication n'est pas celui de l'addition.
Le schéma commun aux deux programmes s'appelle un ACCUMULATEUR, et il structure une grande partie de l'algorithmique du lycée. On initialise une variable à la valeur neutre, 0 pour une somme et 1 pour un produit ; on parcourt les valeurs ; et à chaque tour on combine l'accumulateur avec la valeur courante. Deux erreurs le guettent : une mauvaise initialisation, comme partir de 0 pour un produit, qui revient à l'exercice 6 d), et un écrasement au lieu d'une accumulation, en écrivant s = k au lieu de s = s + k, qui revient à l'exercice 9 b). Un contrôle simple les détecte toutes deux : dérouler la boucle sur trois tours à la main et comparer au résultat attendu.
s = 0
for k in range(1, 11):
s = s + k*k
print(s)
Exercice 4 : Boucle while et recherche de seuil
Une culture de 5 000 bactéries voit sa population augmenter de 8 % par heure. On considère le programme suivant.
La figure place les sept premières valeurs de n que ce programme calcule, de t=0 à t=6, et le seuil de 10000 bactéries.
n = 5000
t = 0
while n < 10000:
n = n * 1.08
t = t + 1
print(t)
a) Que représente la valeur affichée par ce programme ?
b) Déterminez cette valeur. On donne 1,089≈1,9990 et 1,0810≈2,1589.
c) Pourquoi une boucle while est-elle nécessaire ici, plutôt qu'une boucle for ?
d) Que se passerait-il si le taux d'évolution était nul, c'est-à-dire si la ligne devenait n = n * 1.0 ?
Voir la correction
Réponses
a)Nombre d'heures pour atteindre 10000 bactéries
b)10
c)Nombre de tours inconnu à l'avance
d)Boucle infinie
a)
Elle représente le nombre d'HEURES au bout desquelles la population atteint ou dépasse 10000 bactéries, c'est-à-dire le temps de doublement arrondi à l'heure supérieure. La variable t compte les tours de boucle, et chaque tour correspond à une heure.
b)
Après 9 heures, la population vaut 5000×1,9990≈9995 bactéries : c'est encore strictement inférieur à 10000, donc la condition n < 10000 reste vraie et la boucle continue. Après 10 heures, elle vaut 5000×2,1589≈10795 bactéries, la condition devient fausse et la boucle s'arrête. Le programme affiche 10. Le cas à neuf heures est à cinq bactéries près du seuil : conclure sans calculer aurait conduit à répondre 9.
c)
Parce que le nombre de tours n'est pas CONNU avant l'exécution. Une boucle for exige de fixer le nombre d'itérations à l'avance, alors qu'ici c'est justement ce nombre que l'on cherche. La boucle while est donc l'outil des problèmes de SEUIL, où l'on répète tant qu'une condition tient sans savoir combien de temps.
d)
La valeur de n resterait bloquée à 5000, la condition n < 10000 resterait vraie indéfiniment et la boucle ne s'arrêterait JAMAIS : le programme tournerait sans fin. Une boucle while n'est sûre que si quelque chose progresse réellement vers la sortie à chaque tour, et c'est au programmeur de le garantir.
La question d) énonce la règle de sécurité de toute boucle conditionnelle, et l'exercice 9 en donnera une variante : avant d'écrire un while, il faut identifier ce qui PROGRESSE vers la condition de sortie, et vérifier que cette progression est effective. Ici c'est la multiplication par un facteur strictement supérieur à 1 qui garantit la terminaison ; avec un facteur égal à 1 elle disparaît, avec un facteur inférieur à 1 la population diminuerait et la boucle serait encore infinie. En pratique, on protège souvent le programme en ajoutant un compteur maximal, ce qui transforme une boucle infinie en une erreur signalée.
Exercice 5 : Écrire et utiliser des fonctions
Une fonction se définit avec def, reçoit des paramètres entre parenthèses et renvoie une valeur avec return.
a) Écrivez une fonction aire_rectangle(L, l) qui renvoie l'aire d'un rectangle de longueur L et de largeur l. Donnez le résultat de aire_rectangle(7, 3).
b) Écrivez une fonction est_pair(n) qui renvoie True si n est pair et False sinon.
c) Une élève écrit une fonction affiche_double(x) dont le corps est print(2*x), puis exécute y = affiche_double(5). Que vaut y ? Expliquez.
d) On définit def f(x): return 2*x + 3. Calculez f(0) et f(5), puis résolvez f(x) = 17.
Voir la correction
Réponses
a)return L * l ; 21
b)return n % 2 == 0
c)y vaut None
d)f(0)=3, f(5)=13, x=7
a)
La fonction se réduit à une ligne : return L * l. On obtient aire_rectangle(7, 3) =21. Le mot-clé return est indispensable, comme la question c) va le montrer.
b)
On teste le reste de la division par 2 : return n % 2 == 0. L'expression n % 2 == 0 vaut DÉJÀ True ou False, il est donc inutile d'écrire une structure if renvoyant l'un ou l'autre, même si c'est correct. Un test est une expression comme une autre, on peut le renvoyer directement.
c)
y vaut None. La fonction affiche bien 10 à l'écran, mais elle ne RENVOIE rien : en l'absence de return, Python renvoie automatiquement None. C'est la distinction essentielle entre AFFICHER et RENVOYER, et elle explique la plupart des programmes qui semblent fonctionner mais dont on ne peut pas réutiliser le résultat.
d)
f(0)=2×0+3=3 et f(5)=10+3=13. Pour résoudre f(x)=17, on résout 2x+3=17, soit 2x=14 et x=7. On vérifie : f(7)=14+3=17 ✓. Une fonction Python et une fonction mathématique se manipulent donc de la même façon, la première n'étant qu'une écriture de la seconde.
La question c) mérite d'être retenue comme la distinction la plus utile du chapitre. print COMMUNIQUE avec l'utilisateur, en écrivant sur l'écran, et ce qui est écrit est définitivement perdu pour le programme. return COMMUNIQUE avec le reste du code, en fournissant une valeur qu'on peut stocker, réutiliser, additionner ou passer à une autre fonction. Une fonction sans return est donc inutilisable dans un calcul, quelle que soit la qualité de ce qu'elle affiche. La règle pratique est simple : une fonction qui CALCULE quelque chose doit toujours le renvoyer, et l'affichage se fait ensuite à l'extérieur, avec print(f(5)).
def aire_rectangle(L, l):
return L * l
def est_pair(n):
return n % 2 == 0
def f(x):
return 2*x + 3
Partie B : Niveau contrôle (/50)
Exercice 6 : Parcourir une liste
On considère la liste des notes d'un élève : notes = [12, 8, 15, 9, 18, 11].
a) Donnez les valeurs de len(notes), notes[0], notes[2] et notes[len(notes) - 1].
b) Écrivez l'instruction qui calcule la moyenne des notes, et donnez sa valeur arrondie au centième.
c) Écrivez une boucle qui compte le nombre de notes supérieures ou égales à 12, et donnez le résultat.
d) Écrivez une boucle qui trouve la plus grande note sans utiliser la fonction max, et expliquez pourquoi on initialise avec le premier élément plutôt qu'avec 0.
Voir la correction
Réponses
a)6, 12, 15, 11
b)sum(notes) / len(notes) ≈12,17
c)3
d)18 ; initialiser à 0 échouerait sur des valeurs négatives
a)
len(notes) vaut 6, notes[0] vaut 12, notes[2] vaut 15 et notes[len(notes) - 1] vaut 11. Les indices commencent à ZÉRO, donc le dernier indice est 5 et non 6 : écrire notes[6] provoquerait une erreur d'indice. L'écriture notes[len(notes) - 1] est la façon standard de désigner le dernier élément sans connaître la taille.
b)
On écrit moyenne = sum(notes) / len(notes). La somme vaut 12+8+15+9+18+11=73, donc la moyenne vaut 673≈12,17. Utiliser len(notes) plutôt que 6 rend l'instruction valable pour n'importe quelle liste, ce qui est toujours préférable.
c)
On initialise un COMPTEUR à 0, puis on parcourt la liste en l'incrémentant à chaque note qui vérifie la condition. Les notes concernées sont 12, 15 et 18, donc le compteur vaut 3 à la fin. On notera que 12 compte, l'inégalité étant large.
d)
On initialise avec notes[0], puis on compare chaque élément suivant au maximum courant en le remplaçant s'il est plus grand. Le résultat est 18. Initialiser à 0 serait DANGEREUX : si toutes les valeurs étaient négatives, par exemple des températures hivernales à Montréal comme −12, −8, −15 et −3, l'algorithme renverrait 0, valeur qui n'appartient même pas à la liste. Partir du premier élément garantit que le résultat est toujours une valeur réellement présente.
La question d) illustre un principe qui dépasse largement la recherche d'un maximum : une initialisation doit être NEUTRE pour l'opération considérée, ou tirée des données elles-mêmes. Pour une somme, 0 convient car il est neutre pour l'addition. Pour un produit, c'est 1, comme à l'exercice 3. Pour un maximum, aucune valeur numérique n'est neutre, puisqu'il n'existe pas de plus petit nombre : la seule solution correcte est donc de partir du premier élément. Le même raisonnement vaut pour un minimum, et l'erreur symétrique consisterait à l'initialiser à 0 sur une liste de valeurs toutes positives.
compteur = 0
for note in notes:
if note >= 12:
compteur = compteur + 1
maxi = notes[0]
for note in notes:
if note > maxi:
maxi = note
Exercice 7 : Compléter un programme de seuil
Un capital de 2 000 dollars est placé à un taux annuel de 3 %. On veut savoir au bout de combien d'années il dépasse 3 000 dollars.
Le programme suivant est incomplet, les pointillés doivent être remplacés.
capital = 2000
annee = 0
while capital < ... :
capital = capital * ...
annee = annee + 1
print(annee)
a) Complétez les deux pointillés.
b) Déterminez le nombre d'années affiché. On donne 1,0313≈1,4685 et 1,0314≈1,5126.
c) Quel est le capital atteint à cette date, arrondi au centime ?
d) On ajoute une instruction d'affichage à l'intérieur de la boucle pour suivre l'évolution année par année. Combien de lignes cette instruction affiche-t-elle ?
Voir la correction
Réponses
a)3000 et 1.03
b)14 ans
c)≈3025,18 dollars
d)14 lignes, 15 avec le print final
a)
La condition de poursuite est capital < 3000 et la ligne de calcul est capital = capital * 1.03. Augmenter de 3% revient à MULTIPLIER par 1+1003=1,03, et non à ajouter 3 : la confusion entre hausse relative et hausse absolue est l'erreur classique de ce type d'énoncé.
b)
Après 13 ans, le capital vaut 2000×1,4685≈2937,07 dollars, encore inférieur à 3000 : la boucle continue. Après 14 ans, il vaut 2000×1,5126≈3025,18 dollars, la condition devient fausse et la boucle s'arrête. Le programme affiche 14.
c)
Le capital atteint est d'environ 3025,18 dollars. Il DÉPASSE le seuil de 25,18 dollars, ce qui est normal : le capital avance par paliers, année par année, et tombe rarement pile sur le seuil. Une boucle de seuil renvoie donc le premier instant où la condition est franchie, pas l'instant exact du franchissement.
d)
L'affichage se trouvant DANS le corps de la boucle, il s'exécute une fois par tour. Comme la boucle effectue 14 tours, cette instruction affiche 14 lignes ; avec le print(annee) final, le programme en écrit 15 en tout. Si l'affichage était placé APRÈS la boucle, au même niveau d'indentation que le print final, il n'écrirait qu'une ligne : en Python, c'est l'INDENTATION seule qui décide de ce qui est répété, là où d'autres langages utilisent des accolades.
La question d) touche à ce qui distingue Python de la plupart des langages, et à une source d'erreur permanente pour les débutants : l'indentation n'est pas une convention de présentation, c'est de la SYNTAXE. Décaler une ligne de quatre espaces la fait entrer dans la boucle ou en sortir, et change donc le programme. Deux vérifications s'imposent devant tout code à trous : d'abord ce qui est répété et ce qui ne l'est pas, ensuite ce qui doit être initialisé AVANT la boucle, ici capital et annee, car capital = 2000 placé dans la boucle la rendrait infinie, et annee = 0 placé dans la boucle ferait afficher 1.
capital = 2000
annee = 0
while capital < 3000:
capital = capital * 1.03
annee = annee + 1
print(annee, capital)
print(annee)
Exercice 8 : Simulation aléatoire et fluctuation
On simule des lancers d'un dé équilibré à six faces à l'aide du programme suivant. La fonction randint(1, 6) renvoie un entier au hasard entre 1 et 6 inclus.
La question d) utilise l'intervalle de fluctuation en n1, qui n'est plus au programme de Seconde depuis la rentrée 2026 : les questions a) à c), sur la loi des grands nombres observée par simulation, restent au programme.
La figure montre une exécution réelle d'un programme de ce type : au fil de 1000 lancers, la fréquence du 6 est relevée tous les dix lancers. Une autre exécution donnerait une autre courbe.
from random import randint
def simulation(n):
compteur = 0
for i in range(n):
if randint(1, 6) == 6:
compteur = compteur + 1
return compteur / n
a) Que représente la valeur renvoyée par simulation(1000) ?
b) Autour de quelle valeur ce résultat doit-il se situer ? Donnez-la au millième.
c) Deux exécutions de simulation(100) renvoient 0.14 puis 0.19. Est-ce le signe d'une erreur de programme ?
d) On rappelle qu'un intervalle de fluctuation au seuil de 95 % est donné par [p−n1;p+n1]. Comparez sa largeur pour n=100 et pour n=10000.
Voir la correction
Réponses
a)Fréquence du 6 sur 1000 lancers
b)61≈0,167
c)Non : fluctuation d'échantillonnage
d)Largeurs 0,2 et 0,02
a)
Elle représente la FRÉQUENCE d'apparition du 6 sur mille lancers simulés, c'est-à-dire le nombre de 6 obtenus divisé par le nombre de lancers. C'est une fréquence OBSERVÉE, résultat d'une expérience, et non une probabilité, qui est une valeur théorique.
b)
Le dé étant équilibré, la probabilité d'obtenir un 6 vaut 61≈0,167. La fréquence observée doit donc se situer AUTOUR de cette valeur, sans nécessairement l'atteindre.
c)
Non, c'est parfaitement normal : c'est la FLUCTUATION D'ÉCHANTILLONNAGE. Deux échantillons de même taille tirés de la même expérience donnent en général des fréquences différentes, et c'est le propre du hasard. Un programme qui renverrait toujours la même fréquence, par exemple 0,17, à chaque exécution serait au contraire suspect, et signalerait probablement un générateur défectueux. La courbe de l'énoncé montre cette fluctuation au cours d'une seule simulation : la fréquence bouge beaucoup sur les premiers lancers, puis ses variations se resserrent.
d)
Pour n=100, l'intervalle vaut [61−0,1;61+0,1], soit environ [0,067;0,267], de largeur 0,2. Les deux résultats observés, 0,14 et 0,19, y figurent bien ✓. Pour n=10000, l'intervalle vaut [61−0,01;61+0,01], soit environ [0,157;0,177], de largeur 0,02.
Le rapport entre les deux largeurs est le résultat le plus important de l'exercice, et il est contre-intuitif : multiplier la taille de l'échantillon par CENT ne divise la largeur que par DIX, puisque c'est n qui intervient et non n. Gagner une décimale de précision coûte donc cent fois plus de lancers, ce qui explique le prix des sondages et pourquoi ceux-ci se contentent presque tous d'un millier de personnes, avec une marge d'environ trois points. Sur le fond, cet exercice fait le lien entre la simulation informatique et les probabilités : le programme ne démontre rien, mais il permet d'OBSERVER une loi théorique et surtout de constater que l'écart entre théorie et observation est prévisible, ce qui est le point de départ de toute la statistique inférentielle.
Exercice 9 : Quatre programmes à corriger
Chacun des programmes suivants contient une erreur. Identifiez-la, expliquez son effet et proposez la correction.
a) Une fonction moyenne(a, b) dont le corps est print((a + b)/2), appelée par m = moyenne(4, 6). Que vaut m ?
b) Un programme initialise s à 0, puis pour k de 1 à 10 effectue s = k. Que vaut s à la fin, et que voulait-on ?
c) Un programme initialise n à 10, puis exécute while n > 0: avec pour seul corps print(n).
d) Un programme contient la ligne if x = 5:.
Voir la correction
Réponses
a)m vaut None ; remplacer print par return
b)s=10 au lieu de 55 ; écrire s = s + k
c)Boucle infinie ; ajouter n = n - 1
d)if x == 5:
a)
m vaut None. La fonction affiche bien 5 à l'écran, mais elle ne renvoie AUCUNE valeur, et Python renvoie alors None par défaut. La correction consiste à remplacer print par return : return (a + b)/2. On peut toujours afficher le résultat ensuite, depuis l'extérieur, avec print(moyenne(4, 6)). C'est exactement le piège de l'exercice 5 c).
b)
À la fin, s vaut 10 : à chaque tour on ÉCRASE la valeur précédente au lieu de l'accumuler, si bien que seul le dernier passage laisse une trace. On voulait la somme des entiers de 1 à 10, soit 55. La correction est s = s + k, qui ajoute au lieu de remplacer. La différence entre 10 et 55 montre à quel point un seul caractère manquant change tout.
c)
La variable n n'est jamais modifiée dans la boucle, donc la condition n > 0 reste vraie indéfiniment : la boucle est INFINIE et le programme affiche 10 sans jamais s'arrêter. Il faut ajouter n = n - 1 dans le corps, ce qui affichera alors 10, 9, 8, jusqu'à 1, soit dix lignes. C'est la même faute qu'à l'exercice 4 d), sous une autre forme.
d)
C'est une erreur de SYNTAXE. Le simple = est l'affectation, qui range une valeur dans une variable ; le test d'égalité s'écrit avec un double ==. La ligne correcte est if x == 5:. Python refuse d'exécuter le programme, ce qui est ici une chance : l'erreur est signalée immédiatement plutôt que de produire silencieusement un mauvais résultat, comme le font les trois précédentes.
Ces quatre erreurs se classent en deux familles, et la distinction est instructive. L'erreur d) est SYNTAXIQUE : le programme ne démarre même pas, l'ordinateur la signale et elle se corrige en dix secondes. Les erreurs a), b) et c) sont LOGIQUES : le programme s'exécute sans se plaindre et produit un résultat faux, ou ne s'arrête pas. Ce sont de loin les plus dangereuses, précisément parce que rien ne les signale, et le seul moyen de les détecter est de tester le programme sur un cas dont on connaît la réponse. C'est aussi pourquoi savoir dérouler une exécution à la main, comme à l'exercice 1, reste indispensable même quand on dispose d'une machine.
def moyenne(a, b):
return (a + b)/2
s = 0
for k in range(1, 11):
s = s + k
n = 10
while n > 0:
print(n)
n = n - 1
Exercice 10 : Problème de synthèse : une racine carrée par balayage
On cherche une valeur approchée de la solution positive de l'équation x2=7, sans utiliser la touche racine carrée de la calculatrice.
On considère le programme suivant.
La figure trace la courbe de x↦x2 et la droite d'équation y=7 : la lecture graphique situe la solution entre 2,5 et 3, et le programme affine cette lecture.
x = 0
while x*x < 7:
x = x + 0.1
print(x)
a) Quel encadrement d'amplitude 0,1 ce programme fournit-il ? Justifiez par deux calculs.
b) Comment modifier le programme pour obtenir un encadrement d'amplitude 0,01 ? Donnez cet encadrement.
c) L'accumulation de nombreux ajouts de 0,1 pose un problème de précision en machine. Proposez une version qui boucle sur des entiers pour l'éviter.
d) Combien de tours de boucle la version au centième effectue-t-elle ? Que faudrait-il pour gagner une décimale de plus, et pourquoi préfère-t-on souvent la dichotomie, qui divise l'amplitude de l'encadrement par deux à chaque étape ?
Voir la correction
Réponses
a)2,6<7<2,7
b)Pas 0,01 : 2,64<7<2,65
c)Boucler sur un entier n et tester n/100
d)265 tours ; dichotomie en 7 étapes
a)
La boucle continue TANT QUE le carré reste strictement inférieur à 7, et s'arrête dès qu'il l'atteint. On a 2,62=6,76<7, donc la boucle continue, et 2,72=7,29≥7, donc elle s'arrête. Le programme affiche environ 2,7 et fournit l'encadrement 2,6<7<2,7. La valeur affichée est la borne SUPÉRIEURE, la borne inférieure étant la valeur précédente.
b)
Il suffit de remplacer le pas par 0,01, c'est-à-dire d'écrire x = x + 0.01. On a 2,642=6,9696<7 et 2,652=7,0225≥7, d'où l'encadrement 2,64<7<2,65. La calculatrice confirme 7≈2,6458 ✓.
c)
Le nombre 0,1 n'a pas d'écriture BINAIRE exacte, pas plus que 31 n'en a en décimal : en l'ajoutant des centaines de fois, les petites erreurs s'accumulent et la variable finit par valoir un nombre légèrement différent de celui attendu. On contourne le problème en comptant avec un ENTIER et en ne divisant qu'au moment du test : on initialise n à 0, la condition devient while (n/100)*(n/100) < 7:, le corps devient n = n + 1, et l'on affiche n/100 à la fin. Les entiers, eux, sont représentés exactement.
d)
La boucle s'arrête pour n=265, puisque (100265)2=7,0225≥7 alors que la valeur précédente est inférieure : elle effectue donc 265 tours. Pour gagner une décimale, il faudrait un pas dix fois plus petit, donc environ dix fois plus de tours : 2646 exactement. Le nombre de tours est proportionnel à l'inverse du pas : chaque décimale de plus multiplie le travail par dix.
C'est précisément ce coût, multiplié par dix à chaque décimale, qui fait préférer une autre méthode, la DICHOTOMIE. Partant de l'intervalle [2;3], dont on sait qu'il contient 7 puisque 4<7<9, on coupe en deux à chaque étape et l'on garde la moitié qui contient la solution. L'amplitude est alors divisée par deux à chaque tour, donc atteindre 0,01 ne demande que sept étapes, car 271≈0,0078<0,01 alors que 261≈0,0156 est encore trop grand. Sept étapes contre deux cent soixante-cinq, et l'écart s'accroît encore avec la précision : gagner une décimale supplémentaire ne coûte que trois ou quatre étapes de plus, contre dix fois plus de tours pour le balayage. C'est l'illustration la plus simple de ce qu'un meilleur algorithme vaut mieux qu'une machine plus rapide.
n = 0
while (n/100)*(n/100) < 7:
n = n + 1
print(n/100)
Partie C : les classiques (/50)
Exercice 11 : Diviseurs et nombres premiers en Python
On considère la fonction suivante, qui compte les diviseurs d'un entier n≥1. On rappelle que n % d est le reste de la division de n par d.
Un nombre premier est un entier qui a exactement deux diviseurs, 1 et lui-même. Cette notion n'est plus au programme de Seconde depuis la rentrée 2026 : elle sert ici d'entraînement aux boucles et aux tests de divisibilité.
def nb_diviseurs(n):
c = 0
for d in range(1, n + 1):
if n % d == 0:
c = c + 1
return c
a) Que renvoie nb_diviseurs(12) ? Donnez la liste des diviseurs comptés.
b) Que renvoie nb_diviseurs(13) ? Combien de tours de boucle ont été effectués ?
c) Écrivez une fonction est_premier(n) qui utilise nb_diviseurs. Que renvoie-t-elle pour n=1 ?
d) Combien d'entiers compris entre 1 et 30 sont premiers ?
e) Une version plus rapide ne teste les diviseurs d que tant que d×d≤n, en partant de d=2. Combien de tours fait-elle pour n=97 ?
Voir la correction
Réponses
a)6 diviseurs : 1, 2, 3, 4, 6, 12
b)2, en 13 tours
c)return nb_diviseurs(n) == 2 ; False pour 1
d)10 nombres premiers
e)8 tours
a)
La boucle teste d=1, 2, ..., 12 et compte ceux pour lesquels le reste est nul : 1, 2, 3, 4, 6, 12. La fonction renvoie 6. Le range(1, n + 1) est nécessaire pour que n lui-même soit testé, la borne de droite étant exclue.
b)
13 n'a que deux diviseurs, 1 et 13 : la fonction renvoie 2. La boucle a tourné 13 fois, autant que la valeur de n : pour un grand nombre, cette méthode est lente.
c)
Un nombre premier a EXACTEMENT deux diviseurs : return nb_diviseurs(n) == 2. Pour n=1, nb_diviseurs(1) vaut 1, donc la fonction renvoie False : 1 n'est pas premier, et la définition par « exactement deux diviseurs » règle ce cas sans exception à écrire.
d)
Les nombres premiers inférieurs à 30 sont 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 : il y en a 10. Une boucle for n in range(1, 31) qui incrémente un compteur quand est_premier(n) est vrai donne ce résultat.
e)
Si n a un diviseur autre que 1 et lui-même, il en a un qui vérifie d×d≤n. Pour n=97, on teste d=2, 3, ..., 9, car 9×9=81≤97 mais 10×10=100>97 : 8 tours au lieu de 97. Aucun ne divise 97, qui est donc premier.
Le fil : un test de divisibilité s'écrit avec %, un comptage avec un compteur initialisé à 0, et une remarque mathématique (s'arrêter à n) vaut mieux qu'une machine plus rapide.
def est_premier(n):
return nb_diviseurs(n) == 2
compteur = 0
for n in range(1, 31):
if est_premier(n):
compteur = compteur + 1
print(compteur)
Exercice 12 : Types et opérations en Python
Python distingue les entiers (int), les flottants (float), les chaînes de caractères (str) et les booléens (bool). Répondez sans machine, puis vérifiez si vous le souhaitez.
a) Que valent 17 // 5, 17 % 5 et 17 / 5 ?
b) Que valent 2 ** 10 et -7 // 2 ?
c) De quel type est le résultat de 10 / 2 ?
d) Que valent 'ha' * 3 et '3' + '4' ?
e) Que valent (5 > 3) and (2 == 3) et not (4 < 2) ?
Voir la correction
Réponses
a)3, 2 et 3,4
b)1024 et −4
c)float (5.0)
d)'hahaha' et '34'
e)False et True
a)
// est la division ENTIÈRE : 17=3×5+2, donc 17 // 5 vaut 3 et 17 % 5, le reste, vaut 2. La division / donne le quotient décimal : 3,4.
b)
** est la puissance : 2 ** 10 vaut 1024 (et non 2 * 10). -7 // 2 vaut −4 et non −3 : la division entière arrondit vers le BAS, et −3,5 arrondi vers le bas donne −4. C'est le piège classique des nombres négatifs.
c)
La division / renvoie toujours un flottant, même quand le résultat tombe juste : 10 / 2 vaut 5.0, de type float. Pour obtenir l'entier 5, il faut 10 // 2.
d)
Multiplier une chaîne par un entier la RÉPÈTE : 'ha' * 3 vaut 'hahaha'. Additionner deux chaînes les COLLE : '3' + '4' vaut '34', et non 7. Les guillemets font toute la différence entre le nombre 3 et le caractère '3'.
e)
5 > 3 vaut True et 2 == 3 vaut False ; and exige les deux, donc le résultat est False. 4 < 2 vaut False, et not le transforme en True.
À retenir : le même symbole ne fait pas la même chose selon le type des valeurs. + additionne des nombres mais colle des chaînes, et / renvoie toujours un flottant.
Exercice 13 : L'algorithme d'Euclide
La fonction suivante calcule le PGCD (plus grand diviseur commun) de deux entiers naturels non nuls par l'algorithme d'Euclide : on remplace le couple (a;b) par (b;r), où r est le reste de la division de a par b, jusqu'à ce que le reste soit nul.
Le PGCD et l'algorithme d'Euclide ne sont pas au programme de Seconde : ils sont étudiés en Terminale, dans l'option mathématiques expertes. L'exercice sert d'entraînement à la boucle while. Deux entiers dont le PGCD vaut 1 sont dits premiers entre eux.
def pgcd(a, b):
while b != 0:
r = a % b
a = b
b = r
return a
a) Faites tourner pgcd(84, 36) à la main. Combien de tours de boucle sont effectués, et que renvoie la fonction ?
b) Même question pour pgcd(1071, 462).
c) Que renvoie pgcd(17, 5) ? Que peut-on en dire des nombres 17 et 5 ?
d) Que se passe-t-il si l'on appelle pgcd(36, 84), avec le plus petit nombre en premier ? Combien de tours ?
e) Déduisez de la question b) la forme irréductible de la fraction 4621071.
Voir la correction
Réponses
a)2 tours, PGCD 12
b)3 tours, PGCD 21
c)1 : premiers entre eux
d)Échange au premier tour ; 3 tours, PGCD 12
e)2251
a)
Départ a=84, b=36. Tour 1 : r=84%36=12, puis a=36, b=12. Tour 2 : r=36%12=0, puis a=12, b=0. La condition b != 0 est fausse : la boucle s'arrête après 2 tours et la fonction renvoie 12. Contrôle : 84=12×7 et 36=12×3 ✓.
b)
1071=2×462+147 ; 462=3×147+21 ; 147=7×21+0. Trois tours, et la fonction renvoie 21. Chercher tous les diviseurs de 1071 aurait été bien plus long.
c)
17%5=2, puis 5%2=1, puis 2%1=0 : la fonction renvoie 1 après 3 tours. Le seul diviseur commun est 1 : les nombres 17 et 5 sont PREMIERS ENTRE EUX.
d)
Tour 1 : r=36%84=36, puis a=84, b=36. Le premier tour a simplement ÉCHANGÉ les deux nombres. On retrouve ensuite la question a) : 3 tours au total, résultat 12. L'algorithme n'a donc pas besoin qu'on range les nombres dans l'ordre.
e)
On divise numérateur et dénominateur par le PGCD 21 : 4621071=2251. Comme on a divisé par le plus grand diviseur commun, la fraction obtenue est irréductible.
Le point de méthode : une boucle while convient ici parce qu'on ne sait pas d'avance combien de divisions seront nécessaires, et la terminaison est garantie car le reste diminue strictement à chaque tour.
Exercice 14 : Problème : programmer un tarif de taxi
Un taxi facture 4 euros de prise en charge, qui incluent les 2 premiers kilomètres. Chaque kilomètre suivant coûte 1,50 euro, et au-delà de 20 km chaque kilomètre supplémentaire ne coûte plus que 1,20 euro.
On traduit ce tarif par la fonction Python ci-dessous, où d est la distance en kilomètres.
b) Calculez le prix pour 20 km avec la deuxième branche, puis avec la troisième. Le tarif présente-t-il un saut à 20 km ?
c) Quelle distance peut-on parcourir pour exactement 13 euros ?
d) Quelle distance maximale, au centième de kilomètre, peut-on parcourir avec 50 euros ?
e) On veut le plus petit nombre ENTIER de kilomètres pour lequel le prix dépasse strictement 25 euros. Donnez-le.
Voir la correction
Réponses
a)4, 16 et 43 euros
b)31 euros des deux côtés : pas de saut
c)8 km
d)≈35,83 km
e)17 km
a)
tarif(1) : 1≤2, première branche, 4 euros. tarif(10) : deuxième branche, 4+1,5×8=16 euros. tarif(30) : troisième branche, 4+1,5×18+1,2×10=4+27+12=43 euros. On retire bien les 2 km inclus, puis les 18 km facturés à 1,50.
b)
Deuxième branche : 4+1,5×18=31. Troisième branche : 4+27+1,2×0=31. Les deux coïncident : pas de saut à 20 km, le tarif est continu. Un tarif mal écrit, par exemple 4+1,2×(d−2) après 20 km, ferait brutalement baisser le prix de 5,40 euros à 20,01 km.
c)
13 euros est entre 4 et 31 : deuxième branche. 4+1,5(d−2)=13 donne 1,5(d−2)=9, d−2=6 et d=8 km.
d)
50 euros dépasse 31 : troisième branche. 31+1,2(d−20)=50 donne d−20=1,219≈15,83, donc d≈35,83 km.
e)
Deuxième branche : 4+1,5(d−2)>25 équivaut à d−2>14, soit d>16. Pour d=16, le prix vaut exactement 25 ; pour d=17, il vaut 26,50. Le plus petit entier est 17 km. Une boucle while tarif(d) <= 25: d = d + 1 partant de d=0 donne le même résultat.
Ce problème traduit une fonction définie par morceaux en instructions conditionnelles : chaque branche correspond à un intervalle, et l'ORDRE des tests garantit que chaque distance tombe dans la bonne.
Exercice 15 : Problème : résoudre une équation par dichotomie
On cherche la solution de l'équation x3+x−5=0 sur [1;2]. On note f(x)=x3+x−5 ; la fonction f est croissante sur cet intervalle.
Le programme ci-dessous coupe l'intervalle en deux à chaque tour et garde la moitié où f change de signe.
def f(x):
return x**3 + x - 5
a = 1
b = 2
while b - a > 0.01:
m = (a + b) / 2
if f(a) * f(m) <= 0:
b = m
else:
a = m
print(a, b)
a) Calculez f(1) et f(2). Pourquoi l'équation a-t-elle une solution dans [1;2] ?
b) Faites le premier tour à la main : valeur de m, valeur de f(m), nouvel intervalle.
c) Donnez les intervalles obtenus après le deuxième et le troisième tour.
d) Combien de tours la boucle effectue-t-elle au total ?
e) Donnez une valeur approchée au centième de la solution.
Voir la correction
Réponses
a)f(1)=−3<0<5=f(2), f croissante
b)m=1,5, f(m)=−0,125 : [1,5;2]
c)[1,5;1,75] puis [1,5;1,625]
d)7 tours
e)≈1,52
a)
f(1)=1+1−5=−3 et f(2)=8+2−5=5. La fonction passe d'une valeur négative à une valeur positive, et sa courbe se trace sans lever le crayon, puisque c'est une fonction polynôme : elle coupe donc l'axe des abscisses entre 1 et 2. Comme elle est croissante, elle ne le coupe qu'une fois. (Le théorème qui justifie cet argument, celui des valeurs intermédiaires, est vu en Terminale.)
b)
m=21+2=1,5 et f(1,5)=3,375+1,5−5=−0,125. Comme f(1)×f(1,5)=(−3)×(−0,125)>0, les deux sont de même signe : la solution n'est pas dans [1;1,5]. On pose a = m et le nouvel intervalle est [1,5;2].
c)
Tour 2 : m=1,75, f(1,75)≈2,109>0, changement de signe avec f(1,5)<0 : on pose b = m, intervalle [1,5;1,75]. Tour 3 : m=1,625, f(1,625)≈0,916>0 : intervalle [1,5;1,625].
d)
L'amplitude vaut 1 au départ et est divisée par 2 à chaque tour. La boucle continue tant que l'amplitude dépasse 0,01 : après 6 tours elle vaut 641≈0,0156, encore trop grande ; après 7 tours, 1281≈0,0078. La boucle effectue 7 tours.
e)
Après 7 tours, l'intervalle est [1,515625;1,5234375]. Tous ses nombres arrondis au centième donnent 1,52 : la solution vaut environ 1,52. Contrôle : f(1,52)≈0,032, proche de 0 ✓.
La dichotomie est l'algorithme type du chapitre : à chaque tour elle gagne un bit de précision, là où un balayage au pas de 0,01 aurait demandé jusqu'à cent tours.
Il manque quelque chose dans cette série ?Un type d'exercice que ton prof donne, un énoncé qui te bloque, une erreur repérée : dis-le-moi, je lis chaque demande.
L'envoi passe par ton espace gratuit : c'est ce qui me permet de te répondre et de te prévenir quand l'exercice est ajouté. Un courriel suffit, pas de mot de passe. Crée ton espace.
Pas envie de créer un compte ? Écris-moi directement.
Vous cherchez un tuteur de maths en Seconde à Montréal ?
Contactez-moi pour une première séance. On travaille sur des exercices calibrés sur le niveau réel des contrôles au Lycée Marie de France et au Collège Stanislas.