IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Résultat étonnant (pour un débutant) de sqrt


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    ...
    Inscrit en
    Septembre 2015
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2015
    Messages : 31
    Points : 5
    Points
    5
    Par défaut Résultat étonnant (pour un débutant) de sqrt
    Bonjour,

    Je suis débutant et je suis en train de me former au langage Python.
    J'utilise sous Linux la version Python 2.7.6

    je cherche à comparer 2 valeurs identiques l'une est donnée par l'utilisateur et l'autre est calculée avec la racine carrée de 2.
    Voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from math import sqrt
     
    a = input("Entrez une valeur: ")
    b = 20
    c = b * sqrt(2)
     
    print "a =", a
    print "c =", c
     
    if(a == c):
      print "GAGNÉ"
    else:
      print a, "est différent de", c
    Voici ce que me renvoi ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Entrez une valeur: 28.2842712475
    a = 28.2842712475
    c = 28.2842712475
    28.2842712475 est différent de 28.2842712475
    Si je n'utilise pas le module sqrt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    a = input("Entrez une valeur: ")
    b = 20.0
    d = 2 ** 0.5
    c = b * d
     
    print "a =", a
    print "c =", c
     
    if(a == c):
      print "GAGNÉ"
    else:
      print a, "est différent de", c
    J'ai la même chose.
    Je dois me planté quelque part mais franchement je sèche lamentablement.

  2. #2
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Salut,

    Comparer des flottants n'est pas aussi simple. Tu dois generalement comparer a une plage de tolerance, du genre (naivement) abs(a - b) <= tolerance.

    Python 3.5 offre math.isclose() qui est bien pratique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >> import math
    >>> math.isclose(28.2842712475, 20*math.sqrt(2))
    True
    >>> math.isclose(28.2842712475, 20*math.sqrt(2), rel_tol=1e-15)
    False
    Sinon, pour les autres version de python. le code de isclose() est fourni dans la doc: https://docs.python.org/3/library/ma...l#math.isclose

  3. #3
    Membre chevronné
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2013
    Messages
    485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2013
    Messages : 485
    Points : 2 151
    Points
    2 151
    Par défaut
    Ton souci est en effet une erreur classique de débutant en informatique: les nombres réels n'existent pas en faite.

    les nombres "réels" en informatique sont en faite une suite de nombres discrétisés.
    c'est à dire qu'à 2 nombres décimaux donnés, il n'existe pas une infinité de nombre compris entre eux, mais un nombre fini.
    C'est aussi ce qui caractérise l'informatique globalement: il y a toujours une limite (nombre minimal, maximal, précision, taille en mémoire, vitesse d’exécution, ...)

    Mais revenons à ton problème, qui n'est pas propre à Python mais bien à tout langage de programmation.
    donc, comme l'explique Mr Zee, il est important de ne jamais essayer de vérifier une égalité stricte entre 2 décimaux, quelque soit le langage utilisé.
    Au mieux, on vérifie si abs(value1-value2)<1e-10 j'ai mis 1e-10 vu que cela semble être le niveau de précision que tu cherches a avoir.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    ...
    Inscrit en
    Septembre 2015
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2015
    Messages : 31
    Points : 5
    Points
    5
    Par défaut
    Merci beaucoup pour vos réponses.

    Laurent 1973 a écrit:
    les nombres "réels" en informatique sont en faite une suite de nombres discrétisés.
    c'est à dire qu'à 2 nombres décimaux donnés, il n'existe pas une infinité de nombre compris entre eux, mais un nombre fini.
    C'est aussi ce qui caractérise l'informatique globalement: il y a toujours une limite (nombre minimal, maximal, précision, taille en mémoire, vitesse d’exécution, ...)
    Après des tests avec le module Decimal j'avais encore plus d'interrogation, mais là avec ton explication c'est beaucoup plus clair pour moi.

    Laurent 1973 a écrit:
    il est important de ne jamais essayer de vérifier une égalité stricte entre 2 décimaux, quelque soit le langage utilisé.
    Au mieux, on vérifie si abs(value1-value2)<1e-10 j'ai mis 1e-10 vu que cela semble être le niveau de précision que tu cherches a avoir.
    dahtah a écrit:
    Comparer des flottants n'est pas aussi simple. Tu dois generalement comparer a une plage de tolerance, du genre (naivement) abs(a - b) <= tolerance.
    J'ai opter pour cette comparaison qui marche du tonnerre et ai testé aussi la solution qui consiste à convertir les flottants en chaîne de caractère pour ensuite comparer deux string et ça marche bien aussi.
    Ceci étant je me demande quelle est la solution la plus pertinente entre la limite de tolérance et la conversion des flottants en chaîne de caractère.

  5. #5
    Membre chevronné
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2013
    Messages
    485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2013
    Messages : 485
    Points : 2 151
    Points
    2 151
    Par défaut
    Je t'invite plutôt à utiliser la technique de contrôle de différence à une tolérance pret pour la comparaison de 2 décimaux.

    Deux raisons pour cela:
    1. Logique: tu veux comparer des décimaux, reste en décimal, ne passe pas par un autre type intermédiaire.
    2. Habitude: ce principe est une règle quelque soit le langage informatique utilisé, c'est plutôt bien de prendre les bonnes habitudes.
      Si demain tu fais du PHP, du VB, du C/C++ ou du Fortran, tu auras eu la bonne habitude.
      Et si tu veux utiliser ta technique de passer par du texte en C par exemple, bonne chance

  6. #6
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Citation Envoyé par Mr ZEE Voir le message
    J'ai opter pour cette comparaison qui marche du tonnerre et ai testé aussi la solution qui consiste à convertir les flottants en chaîne de caractère pour ensuite comparer deux string et ça marche bien aussi.
    Ceci étant je me demande quelle est la solution la plus pertinente entre la limite de tolérance et la conversion des flottants en chaîne de caractère.
    Bonjour,
    Toutes les réponses abordaient la précision.
    Qui a parlé de convertir en chaîne de caractères?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> 100*(1.043-1)
    4.299999999999993
    >>>
    Alors que manifestement le résultat devrait être "4.3"
    La conversion en chaîne de caractère donnerait donc… "4.3" et "4.2"…

    Voilà pourquoi…
    Clodion

  7. #7
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 608
    Points : 2 072
    Points
    2 072
    Par défaut
    ou plus simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> 0.1+0.2
    0.30000000000000004
    Pas d'aide par mp.

  8. #8
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Citation Envoyé par marco056 Voir le message
    ou plus simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> 0.1+0.2
    0.30000000000000004
    Bonsoir,
    Oui, mais là, le passage aux chaînes de caractères et la comparaison des premiers caractères, renvoie une égalité!
    Mais il y a effectivement, sans doutes, plus simple!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> .3 - .1
    0.19999999999999998
    >>>
    Clodion

  9. #9
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Citation Envoyé par Laurent 1973 Voir le message
    Mais revenons à ton problème, qui n'est pas propre à Python mais bien à tout langage de programmation.
    donc, comme l'explique Mr Zee, il est important de ne jamais essayer de vérifier une égalité stricte entre 2 décimaux, quelque soit le langage utilisé.
    Je suis d'accord à (100 - epsilon) % ! Le epsilon pour le "jamais".

    Il y a des cas où la comparaison stricte entre flottants est nécessaire. Le tout est de savoir ce qu'on fait !

    Un exemple (un que je connais bien) : des données géographiques surfaciques qui "s'enchevêtrent" (un puzzle, quoi !).
    En topologie, le "rabouttage" de surfaces ne se fait pas à epsilon près. Un chevauchement est un chevauchement, un trou est un trou (tout ça, entre surfaces).

    Mais c'était juste pour moduler les propos. Je suis OK sur le fond et ma remarque ne s'applique pas au cas du PO. Suffit d'imaginer un script qui vérifie que l'utilisateur saisit bien PI ...
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  10. #10
    Futur Membre du Club
    Homme Profil pro
    ...
    Inscrit en
    Septembre 2015
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2015
    Messages : 31
    Points : 5
    Points
    5
    Par défaut
    Merci pour vos réponses, suggestions et remarques
    Envoyé par Laurent 1973
    1. Logique: tu veux comparer des décimaux, reste en décimal, ne passe pas par un autre type intermédiaire.
    J’adhère complètement, j'avais déjà un antécédent avec une histoire "de torchons et de serviettes", je vais continuer sur les bonnes habitudes
    Envoyé par Clodion
    Qui a parlé de convertir en chaîne de caractères?
    C'est une méthode que j'ai chopé sur le net, mais effectivement j'ai fait des tests comme dans ton exemple où l'égalité n'est pas bonne en passant par la conversion en string.
    En tous cas merci pour ta démonstration
    Envoyé par plxpy
    Il y a des cas où la comparaison stricte entre flottants est nécessaire. Le tout est de savoir ce qu'on fait !
    OK mais comment fait-on une comparaison stricte entre flottants? On passe par une conversion en décimal?
    Envoyé par plxpy
    Suffit d'imaginer un script qui vérifie que l'utilisateur saisit bien PI ...
    Qu'est ce que tu entends par "l'utilisateur saisit bien PI"?

Discussions similaires

  1. [EDI CSS] un édietur CSS sympa pour un débutant
    Par java_fun dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 21/09/2005, 10h44
  2. De l'aide pour un débutant
    Par Abelkims dans le forum Débuter
    Réponses: 21
    Dernier message: 02/09/2005, 11h11
  3. De l'aide pour un débutant
    Par Abelkims dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 16/08/2005, 14h33
  4. Requete pour un débutant
    Par sqlnoob dans le forum Langage SQL
    Réponses: 3
    Dernier message: 20/05/2005, 08h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo