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, tel qu'il est suivi au Lycée Marie de France et au Collège Stanislas à Montréal. Elle couvre les variables et l'affectation, les instructions conditionnelles, les boucles for et while, les fonctions en Python, les listes, la simulation aléatoire, l'algorithme d'Euclide et la résolution d'une équation par dichotomie, en quinze exercices répartis en trois parties.

À 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ée Tape 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.

Ce chapitre fait partie de Mathématiques en Seconde
Avant de commencer Fiche de révision : les pièges et la méthode de ce chapitre

Avant ce chapitre

Ces notions sont supposées acquises ici. Si le premier exercice résiste, le blocage vient presque toujours de l'une d'elles, pas du chapitre lui-même.

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

Rappel de cours

  • • 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é. Confondre les deux produit une erreur de syntaxe.
  • • 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.
  • • 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é.

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.

Tape tes réponses, la page te dit juste ou faux 0/7

a)
b)
c)
d)
Voir la correction

Réponses

  • a) aa : 55, 88, 88, 33 ; bb : 33, 33, 55, 55 ; affiche 3 5
  • b) Il échange aa et bb
  • c) c = a, a = b, b = c
  • d) Affiche 77
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, aa vaut 55 et bb vaut 33. La ligne a = a + b donne a=8a=8, bb restant à 33. La ligne b = a - b utilise le NOUVEAU aa : b=8−3=5b=8-3=5, aa restant à 88. La ligne a = a - b utilise le nouveau bb : a=8−5=3a=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=5a=5 et b=3b=3, on arrive à a=3a=3 et b=5b=5. Le mécanisme est général : la somme a+ba+b est stockée dans aa et sert de mémoire temporaire, dont on extrait successivement l'ancien aa puis l'ancien bb.

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 77. Au moment de l'affectation y = x, Python range dans yy la VALEUR que xx contient alors, c'est-à-dire 77. Modifier xx ensuite ne modifie pas yy : 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+ba=a+b serait absurde et forcerait bb à être nul ; en Python cela signifie calculer a+ba+b avec les valeurs actuelles, puis ranger le résultat dans aa, 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
Instructionabvaleurs de départ53a = a + b83b = a - b85a = a - b35

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.

def mention(note):
    if note >= 16:
        return 'Tres bien'
    elif note >= 14:
        return 'Bien'
    elif note >= 12:
        return 'Assez bien'
    else:
        return 'Pas de mention'
  • a) Donnez la valeur renvoyée par mention(14), mention(11.5), mention(16) et mention(20).
  • b) Que se passerait-il si l'on plaçait le test note >= 12 en premier ? Illustrez avec une note précise.
  • c) Modifiez la fonction pour qu'elle renvoie 'Refuse' lorsque la note est strictement inférieure à 10.
  • d) Un élève écrit if note >= 16 and note >= 14:. Que vaut réellement cette condition ? Quelle était son intention probable ?

Tape tes réponses, la page te dit juste ou faux 0/7

a)
b)
c)
d)
Voir la correction

Réponses

  • a) 'Bien', 'Pas de mention', 'Tres bien', 'Tres bien'
  • b) 1818 donnerait 'Assez bien' : tests suivants inaccessibles
  • c) elif note >= 10 puis else renvoie 'Refuse'
  • d) Équivaut à note >= 16 ; intention : note >= 14 and note < 16
a)

mention(14) renvoie 'Bien' : 1414 n'est pas supérieur ou égal à 1616, le premier test échoue, mais il l'est à 1414 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≥1616\geq 16. mention(20) renvoie également 'Tres bien'.

b)

Tous les tests suivants deviendraient INACCESSIBLES pour les notes élevées : une note de 1818 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é, 1010 venant après 1212 dans la cascade.

d)

La condition équivaut à note >= 16 tout court : si une note est supérieure ou égale à 1616, elle est AUTOMATIQUEMENT supérieure ou égale à 1414, 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 à 1616 ont déjà été interceptées. Remplacer tous les elif par des if indépendants changerait complètement le comportement, chaque test étant alors évalué et la dernière affectation l'emportant. On retiendra enfin la différence entre le test large ≥\geq et le test strict >>, qui décide du sort exact des valeurs frontières comme 1616 en a).

def mention(note):
    if note >= 16:
        return 'Tres bien'
    elif note >= 14:
        return 'Bien'
    elif note >= 12:
        return 'Assez bien'
    elif note >= 10:
        return 'Pas de mention'
    else:
        return 'Refuse'

Exercice 3 : Boucles for

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 ?

Tape tes réponses, la page te dit juste ou faux 0/5

a)
b)
c)
d)
Voir la correction

Réponses

  • a) Somme de 11 à 1010 : 5555
  • b) s = s + k*k : 385385
  • c) 00, 55, 1010, 1515
  • d) 5!=1205!=120
a)

Il calcule la SOMME des entiers de 11 à 1010, puisque range(1, 11) parcourt 11, 22, jusqu'à 1010, la borne 1111 étant exclue. La valeur affichée est 5555, ce que confirme la formule 10×112=55\frac{10\times 11}{2}=55. Écrire range(1, 10) donnerait 4545 : 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=3851+4+9+16+25+36+49+64+81+100=385.

c)

La variable kk prend les valeurs 00, 55, 1010 et 1515. Le TROISIÈME argument est le pas ; la valeur 2020 est exclue, exactement comme dans range(a, b). Il y a donc quatre valeurs et non cinq, et l'on notera que 15+5=2015+5=20 tombe précisément sur la borne exclue.

d)

Il calcule le PRODUIT des entiers de 11 à 55, c'est-à-dire la factorielle de 55. À la fin, pp vaut 1×2×3×4×5=1201\times 2\times 3\times 4\times 5=120. Le point important est l'INITIALISATION : il faut partir de 11 et non de 00, sinon tous les produits successifs seraient nuls et le résultat vaudrait 00. 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, 00 pour une somme et 11 pour un produit ; on parcourt les valeurs ; et à chaque tour on combine l'accumulateur avec la valeur courante. Deux erreurs le guettent, et elles reviennent à l'exercice 9 : une mauvaise initialisation, comme partir de 00 pour un produit, et un écrasement au lieu d'une accumulation, en écrivant s = k au lieu de s = s + k. 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.

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,99901{,}08^{9}\approx 1{,}9990 et 1,0810≈2,15891{,}08^{10}\approx 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 ?

Tape tes réponses, la page te dit juste ou faux 0/4

a)
b)
c)
d)
Voir la correction

Réponses

  • a) Nombre d'heures pour atteindre 10 00010\,000 bactéries
  • b) 1010
  • 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 10 00010\,000 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 99 heures, la population vaut 5 000×1,9990≈9 9955\,000\times 1{,}9990\approx 9\,995 bactéries : c'est encore strictement inférieur à 10 00010\,000, donc la condition n < 10000 reste vraie et la boucle continue. Après 1010 heures, elle vaut 5 000×2,1589≈10 7955\,000\times 2{,}1589\approx 10\,795 bactéries, la condition devient fausse et la boucle s'arrête. Le programme affiche 1010. Le cas à neuf heures est à cinq bactéries près du seuil : conclure sans calculer aurait conduit à répondre 99.

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 à 5 0005\,000, 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 à 11 qui garantit la terminaison ; avec un facteur égal à 11 elle disparaît, avec un facteur inférieur à 11 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.

Tape tes réponses, la page te dit juste ou faux 0/6

a)
b)
c)
d)
Voir la correction

Réponses

  • a) return L * l ; 2121
  • b) return n % 2 == 0
  • c) y vaut None
  • d) f(0)=3f(0)=3, f(5)=13f(5)=13, x=7x=7
a)

La fonction se réduit à une ligne : return L * l. On obtient aire_rectangle(7, 3) =21=21. Le mot-clé return est indispensable, comme la question c) va le montrer.

b)

On teste le reste de la division par 22 : 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 1010 à 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=3f(0)=2\times 0+3=3 et f(5)=10+3=13f(5)=10+3=13. Pour résoudre f(x)=17f(x)=17, on résout 2x+3=172x+3=17, soit 2x=142x=14 et x=7x=7. On vérifie : f(7)=14+3=17f(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.

Tape tes réponses, la page te dit juste ou faux 0/8

a)
b)
c)
d)
Voir la correction

Réponses

  • a) 66, 1212, 1515, 1111
  • b) sum(notes) / len(notes) ≈12,17\approx 12{,}17
  • c) 33
  • d) 1818 ; initialiser à 00 échouerait sur des valeurs négatives
a)

len(notes) vaut 66, notes[0] vaut 1212, notes[2] vaut 1515 et notes[len(notes) - 1] vaut 1111. Les indices commencent à ZÉRO, donc le dernier indice est 55 et non 66 : é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=7312+8+15+9+18+11=73, donc la moyenne vaut 736≈12,17\frac{73}{6}\approx 12{,}17. Utiliser len(notes) plutôt que 66 rend l'instruction valable pour n'importe quelle liste, ce qui est toujours préférable.

c)

On initialise un COMPTEUR à 00, puis on parcourt la liste en l'incrémentant à chaque note qui vérifie la condition. Les notes concernées sont 1212, 1515 et 1818, donc le compteur vaut 33 à la fin. On notera que 1212 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 1818. Initialiser à 00 serait DANGEREUX : si toutes les valeurs étaient négatives, par exemple des températures hivernales à Montréal comme −12-12, −8-8, −15-15 et −3-3, l'algorithme renverrait 00, 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, 00 convient car il est neutre pour l'addition. Pour un produit, c'est 11, 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 à 00 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,46851{,}03^{13}\approx 1{,}4685 et 1,0314≈1,51261{,}03^{14}\approx 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 s'affichent alors ?

Tape tes réponses, la page te dit juste ou faux 0/4

a)
b)
c)
d)
Voir la correction

Réponses

  • a) 3000 et 1.03
  • b) 1414 ans
  • c) ≈3 025,18\approx 3\,025{,}18 dollars
  • d) 1414 lignes
a)

La condition de poursuite est capital < 3000 et la ligne de calcul est capital = capital * 1.03. Augmenter de 3 %3\ \% revient à MULTIPLIER par 1+3100=1,031+\frac{3}{100}=1{,}03, et non à ajouter 33 : la confusion entre hausse relative et hausse absolue est l'erreur classique de ce type d'énoncé.

b)

Après 1313 ans, le capital vaut 2 000×1,4685≈2 937,072\,000\times 1{,}4685\approx 2\,937{,}07 dollars, encore inférieur à 3 0003\,000 : la boucle continue. Après 1414 ans, il vaut 2 000×1,5126≈3 025,182\,000\times 1{,}5126\approx 3\,025{,}18 dollars, la condition devient fausse et la boucle s'arrête. Le programme affiche 1414.

c)

Le capital atteint est d'environ 3 025,183\,025{,}18 dollars. Il DÉPASSE le seuil de 25,1825{,}18 dollars, ce qui est normal : la croissance étant discontinue, année par année, on n'atterrit jamais exactement sur le seuil. Une boucle de seuil renvoie donc toujours le premier instant où la condition est franchie, jamais 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 1414 tours, 1414 lignes s'affichent. Si l'affichage était placé APRÈS la boucle, au même niveau d'indentation que le print final, il n'y en aurait qu'une : 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 une initialisation placée à l'intérieur remettrait le compteur à zéro à chaque tour et produirait une boucle infinie.

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 1n\frac{1}{\sqrt{n}}, 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.

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−1n ; p+1n]\left[p-\frac{1}{\sqrt{n}}\ ;\ p+\frac{1}{\sqrt{n}}\right]. Comparez sa largeur pour n=100n=100 et pour n=10 000n=10\,000.

Tape tes réponses, la page te dit juste ou faux 0/5

a)
b)
c)
d)
Voir la correction

Réponses

  • a) Fréquence du 66 sur 1 0001\,000 lancers
  • b) 16≈0,167\frac{1}{6}\approx 0{,}167
  • c) Non : fluctuation d'échantillonnage
  • d) Largeurs 0,20{,}2 et 0,020{,}02
a)

Elle représente la FRÉQUENCE d'apparition du 66 sur mille lancers simulés, c'est-à-dire le nombre de 66 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 66 vaut 16≈0,167\frac{1}{6}\approx 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 exactement 0,16660{,}1666 à chaque exécution serait au contraire suspect, et signalerait probablement un générateur défectueux.

d)

Pour n=100n=100, l'intervalle vaut [16−0,1 ; 16+0,1]\left[\frac{1}{6}-0{,}1\,;\,\frac{1}{6}+0{,}1\right], soit environ [0,067 ; 0,267][0{,}067\,;\,0{,}267], de largeur 0,20{,}2. Les deux résultats observés, 0,140{,}14 et 0,190{,}19, y figurent bien ✓. Pour n=10 000n=10\,000, l'intervalle vaut [16−0,01 ; 16+0,01]\left[\frac{1}{6}-0{,}01\,;\,\frac{1}{6}+0{,}01\right], soit environ [0,157 ; 0,177][0{,}157\,;\,0{,}177], de largeur 0,020{,}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\sqrt{n} qui intervient et non nn. 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.

0,050,100,150,200,25n = 100n = 10 0000,0670,2670,1570,1770,140,19p = 1/6 ≈ 0,167fréquence

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:.

Tape tes réponses, la page te dit juste ou faux 0/5

a)
b)
c)
d)
Voir la correction

Réponses

  • a) m vaut None ; remplacer print par return
  • b) s=10s=10 au lieu de 5555 ; écrire s = s + k
  • c) Boucle infinie ; ajouter n = n - 1
  • d) if x == 5:
a)

m vaut None. La fonction affiche bien 55 à 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 1010 : à 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 11 à 1010, soit 5555. La correction est s = s + k, qui ajoute au lieu de remplacer. La différence entre 1010 et 5555 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 1010 sans jamais s'arrêter. Il faut ajouter n = n - 1 dans le corps, ce qui affichera alors 1010, 99, 88, jusqu'à 11, 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=7x^{2}=7, sans utiliser la touche racine carrée de la calculatrice.

On considère le programme suivant.

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 une autre méthode ?

Tape tes réponses, la page te dit juste ou faux 0/7

a)
b)
c)
d)
Voir la correction

Réponses

  • a) 2,6<7<2,72{,}6<\sqrt{7}<2{,}7
  • b) Pas 0,010{,}01 : 2,64<7<2,652{,}64<\sqrt{7}<2{,}65
  • c) Boucler sur un entier n et tester n/100
  • d) 265265 tours ; dichotomie en 77 étapes
a)

La boucle continue TANT QUE le carré reste strictement inférieur à 77, et s'arrête dès qu'il l'atteint. On a 2,62=6,76<72{,}6^{2}=6{,}76<7, donc la boucle continue, et 2,72=7,29≥72{,}7^{2}=7{,}29\geq 7, donc elle s'arrête. Le programme affiche environ 2,72{,}7 et fournit l'encadrement 2,6<7<2,72{,}6<\sqrt{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,010{,}01, c'est-à-dire d'écrire x = x + 0.01. On a 2,642=6,9696<72{,}64^{2}=6{,}9696<7 et 2,652=7,0225≥72{,}65^{2}=7{,}0225\geq 7, d'où l'encadrement 2,64<7<2,652{,}64<\sqrt{7}<2{,}65. La calculatrice confirme 7≈2,6458\sqrt{7}\approx 2{,}6458 ✓.

c)

Le nombre 0,10{,}1 n'a pas d'écriture BINAIRE exacte, pas plus que 13\frac{1}{3} 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 à 00, 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=265n=265, puisque (265100)2=7,0225≥7\left(\frac{265}{100}\right)^{2}=7{,}0225\geq 7 alors que la valeur précédente est inférieure : elle effectue donc 265265 tours. Pour gagner une décimale, il faudrait un pas dix fois plus petit, donc environ dix fois plus de tours, soit 2 6502\,650. Le coût croît LINÉAIREMENT avec la précision demandée.

C'est précisément ce coût linéaire qui fait préférer une autre méthode, la DICHOTOMIE. Partant de l'intervalle [2 ; 3][2\,;\,3], dont on sait qu'il contient 7\sqrt{7} puisque 4<7<94<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,010{,}01 ne demande que sept étapes, car 127≈0,0078<0,01\frac{1}{2^{7}}\approx 0{,}0078<0{,}01 alors que 126≈0,0156\frac{1}{2^{6}}\approx 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)
22,22,42,62,83456789y = 72,6 < √7 < 2,72,62,7

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≥1n\geq 1. On rappelle que n % d est le reste de la division de n par d.

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=1n=1 ?
  • d) Combien d'entiers compris entre 11 et 3030 sont premiers ?
  • e) Une version plus rapide ne teste les diviseurs dd que tant que d×d≤nd\times d\leq n, en partant de d=2d=2. Combien de tours fait-elle pour n=97n=97 ?

Tape tes réponses, la page te dit juste ou faux 0/6

a)
b)
c)
d)
e)
Voir la correction

Réponses

  • a) 66 diviseurs : 11, 22, 33, 44, 66, 1212
  • b) 22, en 1313 tours
  • c) return nb_diviseurs(n) == 2 ; False pour 11
  • d) 1010 nombres premiers
  • e) 88 tours
a)

La boucle teste d=1d=1, 22, ..., 1212 et compte ceux pour lesquels le reste est nul : 11, 22, 33, 44, 66, 1212. La fonction renvoie 66. Le range(1, n + 1) est nécessaire pour que nn lui-même soit testé, la borne de droite étant exclue.

b)

1313 n'a que deux diviseurs, 11 et 1313 : la fonction renvoie 22. La boucle a tourné 1313 fois, autant que la valeur de nn : pour un grand nombre, cette méthode est lente.

c)

Un nombre premier a EXACTEMENT deux diviseurs : return nb_diviseurs(n) == 2. Pour n=1n=1, nb_diviseurs(1) vaut 11, donc la fonction renvoie False : 11 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 à 3030 sont 22, 33, 55, 77, 1111, 1313, 1717, 1919, 2323, 2929 : il y en a 1010. 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 nn a un diviseur autre que 11 et lui-même, il en a un qui vérifie d×d≤nd\times d\leq n. Pour n=97n=97, on teste d=2d=2, 33, ..., 99, car 9×9=81≤979\times 9=81\leq 97 mais 10×10=100>9710\times 10=100>97 : 88 tours au lieu de 9797. Aucun ne divise 9797, qui est donc premier.

Le fil : un test de divisibilité s'écrit avec %, un comptage avec un compteur initialisé à 00, et une remarque mathématique (s'arrêter à n\sqrt{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) ?

Tape tes réponses, la page te dit juste ou faux 0/10

a)
b)
c)
d)
e)
Voir la correction

Réponses

  • a) 33, 22 et 3,43{,}4
  • b) 1 0241\,024 et −4-4
  • c) float (5.0)
  • d) 'hahaha' et '34'
  • e) False et True
a)

// est la division ENTIÈRE : 17=3×5+217=3\times 5+2, donc 17 // 5 vaut 33 et 17 % 5, le reste, vaut 22. La division / donne le quotient décimal : 3,43{,}4.

b)

** est la puissance : 2 ** 10 vaut 1 0241\,024 (et non 2 * 10). -7 // 2 vaut −4-4 et non −3-3 : la division entière arrondit vers le BAS, et −3,5-3{,}5 arrondi vers le bas donne −4-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 55, 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 77. Les guillemets font toute la différence entre le nombre 33 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 de deux entiers naturels non nuls par l'algorithme d'Euclide : on remplace le couple (a ; b)(a\ ;\ b) par (b ; r)(b\ ;\ r), où rr est le reste de la division de aa par bb, jusqu'à ce que le reste soit nul.

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 1717 et 55 ?
  • 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 1071462\frac{1071}{462}.

Tape tes réponses, la page te dit juste ou faux 0/9

a)
b)
c)
d)
e)
Voir la correction

Réponses

  • a) 22 tours, PGCD 1212
  • b) 33 tours, PGCD 2121
  • c) 11 : premiers entre eux
  • d) Échange au premier tour ; 33 tours, PGCD 1212
  • e) 5122\frac{51}{22}
a)

Départ a=84a=84, b=36b=36. Tour 1 : r=84 % 36=12r=84\ \%\ 36=12, puis a=36a=36, b=12b=12. Tour 2 : r=36 % 12=0r=36\ \%\ 12=0, puis a=12a=12, b=0b=0. La condition b != 0 est fausse : la boucle s'arrête après 22 tours et la fonction renvoie 1212. Contrôle : 84=12×784=12\times 7 et 36=12×336=12\times 3 ✓.

b)

1071=2×462+1471071=2\times 462+147 ; 462=3×147+21462=3\times 147+21 ; 147=7×21+0147=7\times 21+0. Trois tours, et la fonction renvoie 2121. Chercher tous les diviseurs de 10711071 aurait été bien plus long.

c)

17 % 5=217\ \%\ 5=2, puis 5 % 2=15\ \%\ 2=1, puis 2 % 1=02\ \%\ 1=0 : la fonction renvoie 11 après 33 tours. Le seul diviseur commun est 11 : les nombres 1717 et 55 sont PREMIERS ENTRE EUX.

d)

Tour 1 : r=36 % 84=36r=36\ \%\ 84=36, puis a=84a=84, b=36b=36. Le premier tour a simplement ÉCHANGÉ les deux nombres. On retrouve ensuite la question a) : 33 tours au total, résultat 1212. 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 2121 : 1071462=5122\frac{1071}{462}=\frac{51}{22}. 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 44 euros de prise en charge, qui incluent les 22 premiers kilomètres. Chaque kilomètre suivant coûte 1,501{,}50 euro, et au-delà de 2020 km chaque kilomètre supplémentaire ne coûte plus que 1,201{,}20 euro.

On traduit ce tarif par la fonction Python ci-dessous, où d est la distance en kilomètres.

def tarif(d):
    if d <= 2:
        return 4
    elif d <= 20:
        return 4 + 1.5 * (d - 2)
    else:
        return 4 + 1.5 * 18 + 1.2 * (d - 20)
  • a) Calculez tarif(1), tarif(10) et tarif(30).
  • b) Calculez le prix pour 2020 km avec la deuxième branche, puis avec la troisième. Le tarif présente-t-il un saut à 2020 km ?
  • c) Quelle distance peut-on parcourir pour exactement 1313 euros ?
  • d) Quelle distance maximale, au centième de kilomètre, peut-on parcourir avec 5050 euros ?
  • e) On veut le plus petit nombre ENTIER de kilomètres pour lequel le prix dépasse strictement 2525 euros. Donnez-le.

Tape tes réponses, la page te dit juste ou faux 0/8

a)
b)
c)
d)
e)
Voir la correction

Réponses

  • a) 44, 1616 et 4343 euros
  • b) 3131 euros des deux côtés : pas de saut
  • c) 88 km
  • d) ≈35,83\approx 35{,}83 km
  • e) 1717 km
a)

tarif(1) : 1≤21\leq 2, première branche, 44 euros. tarif(10) : deuxième branche, 4+1,5×8=164+1{,}5\times 8=16 euros. tarif(30) : troisième branche, 4+1,5×18+1,2×10=4+27+12=434+1{,}5\times 18+1{,}2\times 10=4+27+12=43 euros. On retire bien les 22 km inclus, puis les 1818 km facturés à 1,501{,}50.

b)

Deuxième branche : 4+1,5×18=314+1{,}5\times 18=31. Troisième branche : 4+27+1,2×0=314+27+1{,}2\times 0=31. Les deux coïncident : pas de saut à 2020 km, le tarif est continu. Un tarif mal écrit, par exemple 4+1,2×(d−2)4+1{,}2\times(d-2) après 2020 km, ferait brutalement baisser le prix de 5,405{,}40 euros à 20,0120{,}01 km.

c)

1313 euros est entre 44 et 3131 : deuxième branche. 4+1,5(d−2)=134+1{,}5(d-2)=13 donne 1,5(d−2)=91{,}5(d-2)=9, d−2=6d-2=6 et d=8d=8 km.

d)

5050 euros dépasse 3131 : troisième branche. 31+1,2(d−20)=5031+1{,}2(d-20)=50 donne d−20=191,2≈15,83d-20=\frac{19}{1{,}2}\approx 15{,}83, donc d≈35,83d\approx 35{,}83 km.

e)

Deuxième branche : 4+1,5(d−2)>254+1{,}5(d-2)>25 équivaut à d−2>14d-2>14, soit d>16d>16. Pour d=16d=16, le prix vaut exactement 2525 ; pour d=17d=17, il vaut 26,5026{,}50. Le plus petit entier est 1717 km. Une boucle while tarif(d) <= 25: d = d + 1 partant de d=0d=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.

51015202530354010203040504 euros1,50 euro par km31 euros1,20 euro par km20 km

Exercice 15 : Problème : résoudre une équation par dichotomie

On cherche la solution de l'équation x3+x−5=0x^{3}+x-5=0 sur [1 ; 2][1\ ;\ 2]. On note f(x)=x3+x−5f(x)=x^{3}+x-5 ; la fonction ff est croissante sur cet intervalle.

Le programme ci-dessous coupe l'intervalle en deux à chaque tour et garde la moitié où ff 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)f(1) et f(2)f(2). Pourquoi l'équation a-t-elle une solution dans [1 ; 2][1\ ;\ 2] ?
  • b) Faites le premier tour à la main : valeur de m, valeur de f(m)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.

Tape tes réponses, la page te dit juste ou faux 0/9

a)
b)
c)
d)
e)
Voir la correction

Réponses

  • a) f(1)=−3<0<5=f(2)f(1)=-3<0<5=f(2), ff croissante
  • b) m=1,5m=1{,}5, f(m)=−0,125f(m)=-0{,}125 : [1,5 ; 2][1{,}5\ ;\ 2]
  • c) [1,5 ; 1,75][1{,}5\ ;\ 1{,}75] puis [1,5 ; 1,625][1{,}5\ ;\ 1{,}625]
  • d) 77 tours
  • e) ≈1,52\approx 1{,}52
a)

f(1)=1+1−5=−3f(1)=1+1-5=-3 et f(2)=8+2−5=5f(2)=8+2-5=5. La fonction est croissante et passe d'une valeur négative à une valeur positive : elle s'annule une fois entre 11 et 22.

b)

m=1+22=1,5m=\frac{1+2}{2}=1{,}5 et f(1,5)=3,375+1,5−5=−0,125f(1{,}5)=3{,}375+1{,}5-5=-0{,}125. Comme f(1)×f(1,5)=(−3)×(−0,125)>0f(1)\times f(1{,}5)=(-3)\times(-0{,}125)>0, les deux sont de même signe : la solution n'est pas dans [1 ; 1,5][1\ ;\ 1{,}5]. On pose a = m et le nouvel intervalle est [1,5 ; 2][1{,}5\ ;\ 2].

c)

Tour 2 : m=1,75m=1{,}75, f(1,75)≈2,109>0f(1{,}75)\approx 2{,}109>0, changement de signe avec f(1,5)<0f(1{,}5)<0 : on pose b = m, intervalle [1,5 ; 1,75][1{,}5\ ;\ 1{,}75]. Tour 3 : m=1,625m=1{,}625, f(1,625)≈0,916>0f(1{,}625)\approx 0{,}916>0 : intervalle [1,5 ; 1,625][1{,}5\ ;\ 1{,}625].

d)

L'amplitude vaut 11 au départ et est divisée par 22 à chaque tour. La boucle continue tant que l'amplitude dépasse 0,010{,}01 : après 66 tours elle vaut 164≈0,0156\frac{1}{64}\approx 0{,}0156, encore trop grande ; après 77 tours, 1128≈0,0078\frac{1}{128}\approx 0{,}0078. La boucle effectue 77 tours.

e)

Après 77 tours, l'intervalle est [1,515625 ; 1,5234375][1{,}515625\ ;\ 1{,}5234375]. Tous ses nombres arrondis au centième donnent 1,521{,}52 : la solution vaut environ 1,521{,}52. Contrôle : f(1,52)≈0,032f(1{,}52)\approx 0{,}032, proche de 00 ✓.

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,010{,}01 aurait demandé jusqu'à cent tours.

11,52départtour 1tour 2tour 3solution ≈ 1,52
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.

De quoi s'agit-il ?
Je lis chaque demande moi-même, personne d'autre ne la voit. Inutile d'écrire ton nom ou celui de ton école.
Quand ta demande est traitée, tu es prévenu par courriel et dans ton espace.

En envoyant, tu acceptes que je lise ta demande pour y répondre. Elle est gardée avec ton compte, effacée avec lui, et jamais publiée : politique de confidentialité.

Chapitre précédent Probabilités conditionnelles et arbres pondérés Chapitre suivant 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.

© Ahmed Squalli Houssaini. Série publiée sur www.letuteurscientifique.ca/exercices/2nde-algorithmique-python. Libre pour l'usage personnel et en classe ; sa republication ailleurs demande une autorisation écrite (mentions légales).

Voir aussi

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.

Site par Studio Squalli