Page 1 sur 1

Besoin d'une idée pour contourner le problème sqrt en Python

Message non luPosté: 31 Oct 2018, 17:25
de majestyofgaia
Bonjour,

je vous expose mon problème à travers un exemple. Supposons que je veuille créer un programme qui détermine si un triangle dont on connaît les coordonnées des sommets est rectangle en faisant appel au théorème de Pythagore en python (avec la limite des modules présents sur la Casio graph90+E). Si je n'ai pas fait d'erreur, cela pourrait ressembler à ceci :

Code: Tout sélectionner
from math import sqrt

def distance(a, b, c, d):
    return sqrt((c-a)**2+(d-b)**2)

def pythagore(a, b, c):
    return a**2 == b**2 + c**2 or b**2 == a**2 + c**2 or c**2 == a**2 + b**2

def est_rectangle(x_A, y_A, x_B, y_B, x_C, y_C):
    AB = distance(x_A, y_A, x_B, y_B)
    BC = distance(x_B, y_B, x_C, y_C)
    AC = distance(x_A, y_A, x_C, y_C)
    return pythagore(AB, AC, BC)


Or, si nous testons avec O(0;0), I(1;0) et J(0;1), le programme retourne False au lieu de True.

En cherchant un peu, il s'avère que python renvoie :

a ) 2.0 si je tape sqrt(2)**2
b ) False au test suivant : sqrt(2.0)**2 == 2.0
c ) 4.440892098500626 * 10 ^(-16) si je tape sqrt(2)**2 - 2.0

Ce dernier point explique tout, sqrt(2)**2 ne renvoie pas 2.0 mais 2.000000000000000444....

Ma question est la suivante : comment pourrait-on contourner ce problème pour continuer à utiliser la racine carrée en Python ? Parce que dans ce cas là, le Casio Basic fonctionne finalement bien mieux...

Merci.

(PS : ce serait pour le niveau seconde)

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 31 Oct 2018, 17:54
de critor
Ce n'est pas spécifique au Python, le problème était le même avec le langage historique des calculatrices graphiques.

On peut toujours s'amuser à faire des arrondis qui ne seront pas toujours pertinents selon le contexte... Ou se faire une fonction de test d'égalité qui autorisera un léger écart.

Mais le plus fiable, c'est tout simplement que le test ne dépende pas de la racine carrée.

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 31 Oct 2018, 19:40
de majestyofgaia
critor a écrit:Ce n'est pas spécifique au Python, le problème était le même avec le langage historique des calculatrices graphiques.


Certes, mais sur de petites valeurs, le programme marche très bien en Casio Basic. L'exemple de mon poste précédent fonctionne par exemple, alors que sur Python pas du tout. Pédagogiquement, ça m'oblige à changer. Avant je disais simplement aux élèves qu'il fallait se méfier de la calculatrice pour de grandes valeurs, mais qu'elle restait plutôt fiable pour de petites valeurs. Bref, le programme fonctionnait plutôt pas mal. Ici, en python, il ne marche pour ainsi dire jamais si on utilise la racine carrée. Le programme n'a plus aucun intérêt, et cela oblige à expliquer plus explicitement ce problème de codage des nombres à virgule flottante.

critor a écrit:On peut toujours s'amuser à faire des arrondis qui ne seront pas toujours pertinents selon le contexte... Ou se faire une fonction de test d'égalité qui autorisera un léger écart.

Mais le plus fiable, c'est tout simplement que le test ne dépende pas de la racine carrée.


La deuxième proposition est celle que nous avons adoptée pour le moment, mais cela donne l'impression de contourner le problème, plus que de le résoudre.

La première proposition nous l'avons envisagée, mais cela nécessite (enfin, ça semblerait ce qu'il y a de plus naturel) d'introduire la valeur absolue, et donc la distance entre deux nombres. Cela est intéressant, d'autant plus qu'elle revient dans le programme de l'année prochaine en seconde, mais ça fait un obstacle supplémentaire à dépasser. Pour certains élèves, ça risque d'être compliqué.

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 02 Nov 2018, 06:37
de numbermaniac
Does Python's built-in Decimal module work on the calculator?

On computer Python:
Code: Tout sélectionner
>>> from decimal import Decimal as D
>>> D('2').sqrt()**2
Decimal('1.999999999999999999999999999')
>>> D('2').sqrt()**2-2
Decimal('-1E-27')


Still not quite zero... but at this point the error is so small you could use the round function to get zero. Unfortunate, but it's about the best you're going to get from Python. I guess this is where Casio Basic's exact values work better.

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 02 Nov 2018, 10:04
de critor
Thanks, but unfortunately it's not yet available on the Casio fx-CG50 / Graph 90+E :
Image

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 02 Nov 2018, 14:50
de majestyofgaia
En effet, pas de module Décimal, ni Fraction pour le moment. Dommage.

Sinon j'avais une question : sur Casio ou ti, lorsque l'on tape 0,1 + 0,2, la calculatrice affiche 0,3. Mais si j'ai bien compris, ce n'est pas "ce" calcul qu'elle fait, mais elle travaille avec une valeur approchée de 0,1 car elle ne sait pas le coder, idem pour 0,2 et son résultat est une valeur approchée de 0,3. Pourtant, à la fin elle affiche 0,3 comme si de rien n'était, alors que son résultat est probablement différent. Comment cela est-il géré ?

Est-ce que cela a avoir avec le fait qu'elle fait cette erreur ci :
$mathjax$10^{11} -1 = 10^{11}$mathjax$
? Erreur qu'elle ne fait qu'à partir d'une puissance supérieure ou égale à 10. Et donc elle ignore les chiffres au delà du 11ème ? Et affiche une valeur approchée ?

D'ailleurs, numworks ne se fait pas avoir : jusqu'à
$mathjax$10^{100} - 1$mathjax$
elle affiche un entier exact, et au delà d'une puissance de 101, elle renvoie le calcul et en valeur approchée la même erreur que Casio.

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 20 Nov 2018, 14:49
de Lephe
Si tu tapes 0.1 + 0.2 dans l'application RUN/MAT de la Casio, alors le résultats est exactement 0.3 car le moteur de calcul utilisé est décimal. C'est avantageux quand on écrit les nombres en décimal, ça serait complètement inutile si on les écrivait en hexadécimal par exemple. C'est un choix spécifique.

Par contre, le format BCD est similaire à un flottant, et a une mantisse de 14/15 chiffres si je me souviens bien. Comme il ne les affiche pas tout, il est normal que 10^11 et 10^11 - 1 soient affichés pareil ; tu peux peut-être vérifie que (10^11 - 1) - 10^11 et 10^11 - 10^11 sont, eux, différents pour vérifier mon affirmation. (Si je me souviens bien ça échouera à partir de 10^14 ou 10^15).

Pour la racine carrée, le même problème se pose qu'en Python, il y a 14/15 décimales exactes et le reste est tronqué.

Re: Besoin d'une idée pour contourner le problème sqrt en Py

Message non luPosté: 20 Nov 2018, 20:54
de cpierquet
De mémoire les dernières versions de Python incluent la commande isclose(a,b) qui est un test de "presque égalité"... et effectivement dès qu'on travaille avec des flottants, cela peut coincer...