1. Une formule à faire calculer
Le problème du jour : confier les calculs à une machine.
D’après le théorème 2 du cours, si \(\Delta=b^2-4ac>0\), l’équation \(ax^2+bx+c=0\) a deux solutions :
\[x_1=\frac{-b-\sqrt{\Delta}}{2a}\qquad\text{et}\qquad x_2=\frac{-b+\sqrt{\Delta}}{2a}.\]Sans calculatrice, ces formules ne donnent une valeur simple que si \(\Delta\) est un carré parfait. Pour l’équation \(1{,}3x^2-2{,}7x-4{,}1=0\), il faudrait calculer \(\sqrt{28{,}61}\) : c’est hors de portée du calcul mental.
Le but de l’atelier
Écrire un petit programme Python qui calcule les solutions, le vérifier sur un cas connu, puis l’employer sur une équation que l’on ne sait pas résoudre de tête. En chemin, un bug très répandu vous attend.
La barre de fraction groupe tout ce qui est au-dessus et tout ce qui est au-dessous : on calcule le numérateur \(-b+\sqrt{\Delta}\) en entier, le dénominateur \(2a\) en entier, puis on divise l’un par l’autre. C’est ce groupement, évident sur le papier, qu’il faudra écrire pour Python.
2. D’où vient la formule ?
La démonstration du théorème 2, en accéléré.
Al-Khwârizmî, vers 830, résolvait ses équations en complétant un carré dessiné. La formule avec des lettres n’est venue que bien plus tard, quand François Viète (1591) puis René Descartes (1637) ont pris l’habitude de désigner les nombres connus par des lettres. Le principe, lui, n’a pas changé : compléter le carré. Dévoilez la démonstration ligne à ligne.
| \(ax^2+bx+c=0\) | l’équation, avec \(a\neq0\) |
| \(x^2+\dfrac{b}{a}x+\dfrac{c}{a}=0\) | on divise par \(a\) |
| \(\left(x+\dfrac{b}{2a}\right)^2-\dfrac{b^2}{4a^2}+\dfrac{c}{a}=0\) | on complète le carré |
| \(\left(x+\dfrac{b}{2a}\right)^2=\dfrac{b^2-4ac}{4a^2}=\dfrac{\Delta}{(2a)^2}\) | on isole le carré |
| \(x+\dfrac{b}{2a}=\dfrac{\sqrt{\Delta}}{2a}\) ou \(x+\dfrac{b}{2a}=-\dfrac{\sqrt{\Delta}}{2a}\) | si \(\Delta>0\) |
| \(x=\dfrac{-b+\sqrt{\Delta}}{2a}\) ou \(x=\dfrac{-b-\sqrt{\Delta}}{2a}\) | les deux solutions |
Le cours raisonne par disjonction des cas : si \(\Delta<0\), un carré ne peut pas être négatif, il n’y a aucune solution ; si \(\Delta=0\), une seule ; si \(\Delta>0\), les deux ci-dessus. Le programme devra faire de même.
On ne peut pas diviser par \(0\). Or, pour un polynôme du second degré \(ax^2+bx+c\), le coefficient \(a\) n’est jamais nul : sinon il n’y aurait plus de \(x^2\). Le signe de \(a\), lui, n’intervient pas ici.
3. Le programme d’Inès
Un cas connu, pour vérifier l’outil avant de s’en servir.
Inès a recopié les formules dans un programme, en écrivant delta**0.5 pour
\(\sqrt{\Delta}\) (élever à la puissance \(0{,}5\), c’est prendre la racine carrée) :
Elle le teste sur \(x^2-5x+4=0\), dont les solutions sont connues : \(1\) et \(4\)
(\(1-5+4=0\) et \(16-20+4=0\)). Le programme affiche pourtant
[3.5, 6.5]. Voici, dans l’ordre, ce que calcule Python pour
x2 :
| Python calcule | c’est-à-dire | résultat |
|---|---|---|
delta**0.5 | la racine carrée de \(\Delta=9\) | 3.0 |
… / 2 | ce résultat, divisé par \(2\) | 1.5 |
… * a | puis multiplié par \(a=1\) | 1.5 |
-b + … | et enfin ajouté à \(-b=5\) | 6.5 |
Python n’a jamais vu la barre de fraction : il a divisé \(\sqrt{\Delta}\) seul, au lieu de diviser tout \(-b+\sqrt{\Delta}\). Le test sur un cas connu a démasqué le bug.
x2 = -b + delta**0.5/2*a, avec \(a=1\), \(b=2\) et \(c=-3\), c’est-à-dire pour l’équation \(x^2+2x-3=0\). Quelle valeur Python donne-t-il à x2 ? une seule réponse\(\Delta=16\) et \(\sqrt{\Delta}=4\). Python calcule d’abord \(4\div 2=2\), multiplie par \(a=1\), puis ajoute \(-b=-2\) : x2 vaut \(0\). La bonne solution est \(\dfrac{-2+4}{2}=1\) : la ligne fautive ne divise que la racine carrée.
4. Les règles de priorité
1957 : la première machine qui lit des formules.
En 1957, une équipe d’IBM dirigée par John Backus livre FORTRAN, pour FORmula
TRANslation : pour la première fois, on écrit une formule presque comme en mathématiques, et
la machine la traduit en calculs. Il a fallu fixer des règles pour qu’une ligne comme
-b + delta**0.5/2*a n’ait qu’un sens. Python suit les mêmes :
L’ordre des calculs en Python
1. Ce qui est entre parenthèses.
2. Les puissances **.
3. Les multiplications * et divisions /, de gauche à droite.
4. Les additions + et soustractions -, de gauche à droite.
Sur le papier, la barre de fraction groupe d’elle-même le numérateur et le dénominateur.
Sur une seule ligne, ce groupement doit être écrit : \(\dfrac{-b+\sqrt{\Delta}}{2a}\) devient
(-b + delta**0.5) / (2*a).
Il faut des parenthèses autour du numérateur et du dénominateur : (-b + delta**0.5) / (2*a). Sans les secondes, / 2*a divise par \(2\) puis multiplie par \(a\) ; sans les premières, seule la racine est divisée ; -(b + …) change le signe de la racine, et (-b + delta)**0.5 prend la racine du mauvais nombre.
5. Un bug qui se cache
Le test réussit… et pourtant le programme est faux.
Inès corrige d’abord en ajoutant une seule paire de parenthèses :
x2 = (-b + delta**0.5) / 2*a. Elle relance le test sur \(x^2-5x+4\) : cette
fois, le programme affiche [1.0, 4.0]. Le test est réussi.
Mais d’après la règle « de gauche à droite », / 2*a divise par \(2\), puis
multiplie par \(a\). Pour \(a=1\), diviser par \(2a\) ou diviser par \(2\) puis
multiplier par \(a\), c’est la même chose : le test ne pouvait pas voir l’erreur.
Et pour \(a=-1\) ?
Multiplier par \(-1\) ou diviser par \(-1\), c’est encore la même chose : changer le signe. Le calcul fautif donne donc aussi le bon résultat pour \(a=-1\). Il ne se trahit que lorsque \(a\times a\neq1\).
x2 = (-b + delta**0.5) / 2*a est encore fausse. Avec laquelle de ces équations un test la démasquerait-il ? une seule réponse… / 2*a calcule \(\dfrac{-b+\sqrt{\Delta}}{2}\times a\) au lieu de \(\dfrac{-b+\sqrt{\Delta}}{2a}\) : les deux résultats sont égaux quand \(a\times a=1\), c’est-à-dire pour \(a=1\) et aussi pour \(a=-1\). Seule l’équation de coefficient \(a=2\) révèle l’erreur : pour tester un programme, on choisit des cas qui ne cachent rien.
6. À vous : la console Python
Corriger, vérifier, puis s’en servir.
Voici le programme d’Inès, avec ses deux lignes fautives. Ouvrez la console, puis :
1. Exécutez-le : le test affiche [3.5, 6.5].
2. Corrigez les deux lignes x1 = … et x2 = … avec les bonnes
parenthèses, et exécutez à nouveau : le test doit afficher [1.0, 4.0].
3. La seconde ligne affiche alors les solutions de \(1{,}3x^2-2{,}7x-4{,}1=0\).
4. Ajoutez une ligne pour l’équation \(0{,}8x^2-1{,}1x-2{,}7=0\), et répondez à la question ci-dessous.
Si la console ne se charge pas — réseau du lycée, tablette capricieuse —, le même programme s’exécute sur https://sciency.co/console.
Lire les résultats
Avec les deux lignes corrigées, le programme affiche :
La première ligne redonne les solutions connues \(1\) et \(4\) : c’est la preuve que le programme calcule juste. La seconde donne les solutions de \(1{,}3x^2-2{,}7x-4{,}1=0\), environ \(-1{,}02\) et \(3{,}10\). Python écrit les nombres décimaux avec un point et affiche jusqu’à dix-sept chiffres : seuls les premiers comptent.
La ligne à ajouter est print(solutions(0.8, -1.1, -2.7)) (Python écrit les nombres décimaux avec un point). Le programme affiche [-1.274044353309402, 2.649044353309402] : la solution positive vaut environ \(2{,}649\). Sans calculatrice, il aurait fallu calculer \(\sqrt{\Delta}\) avec \(\Delta=9{,}85\) : c’est le travail que le programme fait à notre place.
7. Ce qu’il faut retenir
Le fil, d’un bout à l’autre.
Le raisonnement
La formule \(\dfrac{-b\pm\sqrt{\Delta}}{2a}\) vient de la complétion du carré. Pour la faire calculer par une machine, on l’écrit sur une ligne en rendant visibles les groupements que fait la barre de fraction :
\[\frac{-b+\sqrt{\Delta}}{2a}\;\longrightarrow\;\texttt{(-b + delta**0.5) / (2*a)}\]Un programme se vérifie sur un cas dont on connaît la réponse, choisi pour ne rien cacher (ici \(a\neq1\) et \(a\neq-1\)) ; ensuite seulement, on lui confie les cas hors de portée du calcul à la main.
Votre parcours
Vous avez répondu juste à 0 question(s) sur 6.