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.

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. L'exercice 10 montre pourquoi une boucle qui ajoute 0,1 finit par mentir.

Série autocorrigée Tape tes réponses sous chaque 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.

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=83=5b=8-3=5, aa restant à 88. La ligne `a = a - b` utilise le nouveau bb : a=85=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

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 161616\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,0891,99901{,}08^{9}\approx 1{,}9990 et 1,08102,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 1000010\,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 1000010\,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 5000×1,999099955\,000\times 1{,}9990\approx 9\,995 bactéries : c'est encore strictement inférieur à 1000010\,000, donc la condition `n < 10000` reste vraie et la boucle continue. Après 1010 heures, elle vaut 5000×2,1589107955\,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 à 50005\,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 73612,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,03131,46851{,}03^{13}\approx 1{,}4685 et 1,03141,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) 3025,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 2000×1,46852937,072\,000\times 1{,}4685\approx 2\,937{,}07 dollars, encore inférieur à 30003\,000 : la boucle continue. Après 1414 ans, il vaut 2000×1,51263025,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 3025,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.

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 [p1n ; p+1n]\left[p-\frac{1}{\sqrt{n}}\ ;\ p+\frac{1}{\sqrt{n}}\right]. Comparez sa largeur pour n=100n=100 et pour n=10000n=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 10001\,000 lancers
  • b) 160,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 160,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 [160,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=10000n=10\,000, l'intervalle vaut [160,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.

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,2972{,}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,022572{,}65^{2}=7{,}0225\geq 7, d'où l'encadrement 2,64<7<2,652{,}64<\sqrt{7}<2{,}65. La calculatrice confirme 72,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,02257\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 26502\,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 1270,0078<0,01\frac{1}{2^{7}}\approx 0{,}0078<0{,}01 alors que 1260,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)
11.21.41.61.8212345y = 31,71,8le balayage avance de 0,1 jusqu'à dépasser 3 :√3 est encadré entre 1,7 et 1,8diviser le pas par 10 donne une décimale de plus

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 n1n\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×dnd\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×dnd\times d\leq n. Pour n=97n=97, on teste d=2d=2, 33, ..., 99, car 9×9=81979\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) 10241\,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 10241\,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)` : 121\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×(d2)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(d2)=134+1{,}5(d-2)=13 donne 1,5(d2)=91{,}5(d-2)=9, d2=6d-2=6 et d=8d=8 km.

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

e) Deuxième branche : 4+1,5(d2)>254+1{,}5(d-2)>25 équivaut à d2>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.

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

On cherche la solution de l'équation x3+x5=0x^{3}+x-5=0 sur [1 ; 2][1\ ;\ 2]. On note f(x)=x3+x5f(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+15=3f(1)=1+1-5=-3 et f(2)=8+25=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,55=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 1640,0156\frac{1}{64}\approx 0{,}0156, encore trop grande ; après 77 tours, 11280,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.

Chapitre précédent Les statistiques descriptives 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.

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