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

Langage C++ Discussion :

Comparaison de float/double


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 396
    Par défaut Comparaison de float/double
    Bonjour,

    J'aimerais savoir si dans le code source suivant, (a==b) est toujours true ou pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void fct(float a){
      float b = a;
      // (a==b)==true ???
    }
    Merci d'avance.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Je suppose que vous faites allusion aux problèmes de comparaison de valeurs réelle liées au nombre de chiffres significatifs.
    Il y a eu une discussion dernièrement sur ce sujet.
    Mon avis sur la question : en général la comparaison de 2 flottants avec == n'est jamais true.
    Dans le cas présent, elle est true, parce que a est réellement égal à b, puisque c'est écrit à la ligne précédente.
    Dans le cas général un flottant résulte de calculs, et donc deux flottants ne seront pas égaux.
    On peut par exemple écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    bool Egal(float a, float b, float precis)
    {
      if (fabs(a-b) < precis) return true;
      return false;
    }
    Je crois que ce problème a fait l'objet d'un article dans la FAQ.

  3. #3
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    voici l'article évoqué par Pierre.

    Pour répondre à la question initiale, la relation a==b est toujours vraie dans l'exemple.

    @Pierre :
    Mon avis sur la question : en général la comparaison de 2 flottants avec == n'est jamais true,
    En fait, cela dépend beaucoup trop des situations pour donner une réponse catégorique au problème de la pertinence des tests de comparaison de flottants. Il faut traiter ce type de problème au cas par cas.
    Mathématiquement, le problème est fortement lié à la notion de conditionnement qui apparaît en analyse numérique. Les tests vont également différer selon que l'on considère des algorithmes itératifs ou directs.

    Dans beaucoup de cas, une bonne solution consiste à mixer un test "exact" (a==b) et un test "approximatif" (fabs(b-a)<tolérance) et à indiquer à l'utilisateur un message différent dans chaque cas.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Il est vrai que je me place ans le contexte où les valeurs sont des dimensions.
    Supposons des float, la précision est de 7 chiffres significatifs. Si le 7è est bon, on dira que les 2 valeurs sont égales, si le 6è est bon, mais le à différent de 1 unité, est-il justifié de dire que les deux valeurs ne sont pas égales mais proches, donc, un traitement différent du premier? je ne pense pas.
    Par ailleurs, ce type de test est fait dans un programme qui effectue des quantités de test de ce type.
    Donc, pour moi, sauf cas particulier, c'est à dire dans le cas général, l'égalité de 2 réels n'existe pas.
    Il serait intéressant de nous donner un exemple où "dans le cas général le test d'égalité entre 2 réels a un sens".

    Pour s'en convaincre, voici une petite démonstration, par le contraire (c'est plus facile)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main(int argc, char *argv[])
    {
      float a,b;
      a=MAXFLOAT;
      b=MAXFLOAT;
      a-=1.;
      b-=10.;
      if (a==b) printf("Egal\n");
      else printf("Différent\n");  
      while (!kbhit());
      return 0;
    }
    Le programme trouve que a et b sont égaux. CQFD.
    Pour mémoire, j'ai utilisé MAXFLOAT comme valeur particulière, en l'occurrence, cela voulait dire "valeur non renseignée, donc inconnue". Dans certains cas que j'ai parfaitement identifiés, la valeur ne valait plus EXACTEMENT MAXFLOAT. J'en suis arrivé à prendre comme valeur test 4607.48 qui elle n'était pas atteinte par la modification "accidentlle" du 7è chiffre significatif.
    Dernière modification par Invité ; 02/08/2010 à 12h20.

  5. #5
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    tout d'abord, je pense ne pas comprendre le sens donné au mot "dimensions" dans votre phrase :
    Il est vrai que je me place dans le contexte où les valeurs sont des dimensions.
    J'ai une petite remarque concernant ceci :
    Supposons des float, la précision est de 7 chiffres significatifs.
    La précision d'un float peut théoriquement varier, par exemple en fonction de l'architecture ou du système d'exploitation (voir le fichier float.h). La précision actuelle d'un float sera très certainement différente de celle(s) que l'on trouvera dans les prochaines années.

    Supposons des float, la précision est de 7 chiffres significatifs. Si le 7è est bon, on dira que les 2 valeurs sont égales, si le 6è est bon, mais le à différent de 1 unité, est-il justifié de dire que les deux valeurs ne sont pas égales mais proches, donc, un traitement différent du premier? je ne pense pas.
    Quelles sont vos raisons? Dans votre premier message vous avez écrit :
    Dans le cas général un flottant résulte de calculs, et donc deux flottants ne seront pas égaux.
    Ce raisonnement n'est pas juste. D'une part, les flottants ne résultent pas nécessairement de calculs (constantes physiques/mathématiques,paramètres de tolérance/précision, etc). D'autre part, lorsque c'est le cas, deux flottants issus de calculs différents peuvent être égaux à la précision choisie pour vos opérations (si les nombres 1.23456789 et 1.23456788 sont les résultats théoriques de deux calculs différents et sont stockés dans vos "float", ils seront considérés égaux.)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Par ailleurs, ce type de test est fait dans un programme qui effectue des quantités de test de ce type.
    Je ne vois pas ce qui permet d'affirmer cela. J'imagine que vous voulez écrire que dans ce cas là, la coexistence de deux tests comparatifs dont l'un semble redondant à l'autre implique une perte de performances. C'est parce que vous voyez les choses comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    float a,b;
    // ...calculs avec a et b...
    if (a==b)
    {
        // cas où a et b sont égaux à la précision du calculateur
    }
    else if (fabs(b-a)<=tolerance)
    {
       // cas où a et b sont égaux à la tolérance utilisateur
    }
    alors qu'il faut les voir comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    float a,b;
    // ...calculs avec a et b...
    if (fabs(b-a)<=tolerance)
    {
        if (a==b)
        {
            // cas où a et b sont égaux à la précision du calculateur
        }
        else 
        {
           // cas où a et b sont égaux à la tolérance utilisateur
        }
    }


    Les opérations élémentaires (+,-,*,/) sur les flottants peuvent générer des erreurs d'arrondi en précision finie. Pour paraphraser l'article de la faq :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Ces imprécisions deviennent d'autant plus gênantes qu'elles s'accumulent en même temps que les opérations que vous effectuez sur vos nombres ; ainsi il est tout à fait possible d'obtenir des nombres très éloignés des résultats théoriques.
    L'accumulation des erreurs d'arrondis est une chose qui peut être analysée très finement. En analyse numérique, on utilise des modèles d'arithmétique flottante pour cela.
    L'un des pionniers du domaine est Wilkinson. Le livre d'Higham est une belle introduction à ces questions.

    Un domaine typique où on a recours aux tests que vous préconisez est la géométrie algorithmique, par exemple dans la génération des maillages simpliciaux par l'algorithme de Delaunay.
    Ceci est notamment dû au fait que l'on gère simultanément une représentation flottante et une représentation graphique (entiers<->pixels) des triangulations.

    Pour s'en convaincre, voici une petite démonstration, par le contraire (c'est plus facile)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int main(int argc, char *argv[])
    {
      float a,b;
      a=MAXFLOAT;
      b=MAXFLOAT;
      a-=1.;
      b-=10.;
      if (a==b) printf("Egal\n");
      else printf("Différent\n");  
      while (!kbhit());
      return 0;
    }
    Le programme trouve que a et b sont égaux. CQFD.
    Que démontrez-vous?

    Il serait intéressant de nous donner un exemple où "dans le cas général le test d'égalité entre 2 réels a un sens".
    Par exemple, tous les algorithmes itératifs qui possèdent une propriété de convergence et sont stables-vers-l'avant (forward stability) : la valeur limite peut-être testée à la précision du calculateur.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Ce problème d'égalité ou non de flottant est beaucoup moin compliqué que vous vous imaginez.

    1- une dimension peut être une longueur, un angle, une latitude, une aire, mais pas un prix.

    2- un float est sur 32 bits ce qui implique forcément 7 chiffres significatifs, s'il était sur 64 bits on appellerait ça un double (15 chiffres)

    Citation:
    Supposons des float, la précision est de 7 chiffres significatifs. Si le 7è est bon, on dira que les 2 valeurs sont égales, si le 6è est bon, mais il est différent de 1 unité, est-il justifié de dire que les deux valeurs ne sont pas égales mais proches, donc, un traitement différent du premier? je ne pense pas.
    Quelles sont vos raisons? Dans votre premier message vous avez écrit :
    Citation:
    Dans le cas général un flottant résulte de calculs, et donc deux flottants ne seront pas égaux.
    Ce raisonnement n'est pas juste. D'une part, les flottants ne résultent pas nécessairement de calculs (constantes ...
    Un réel au sens mathématique se différencie d'un entier par ses décimales. Lorsqu'on écrit la 3ème décimale et pas la quatrième, c'est qu'on a arrondi à 1/1000, mais rien ne dit que la quatrième décimale est 0 ainsi que les suivantes.
    Les flottant, c'est strictement la même chose. Quand on fait du calcul numérique avec une table de logarithme avec une table à 5 chiffres, on dispose de 5 chiffres significatifs, amis rien ne dit que le 6è chiffre n'est pas 4.

    Bien sûr un flottant peut ne pas résulter de calcul. Vous parlez de calculs constantes mathématiques. Testez cet exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      float c = M_PI;
      if (c == M_PI) printf("c est Egal à PI\n");
      else printf("c est Différent de PI\n");
    Par ailleurs, ce type de test est fait dans un programme qui effectue des quantités de test de ce type.

    Citation :
    Je ne vois pas ce qui permet d'affirmer cela. J'imagine que vous voulez écrire que dans ce cas là, la coexistence de ...
    Tout simplement parce que je sais ce que font les programme que j'écris

    Dans vos exemples, que fera le programme dans l'une ou l'autre solution? En quoi sont-elles différentes ?
    Je dis que soit un float a une valeur conventionnelle, type MAXFLOAT et on peut tester l'égalité, le résultat du test aura un sens et le programme pourra agir en conséquence, sinon, il est nécessaire de faire le test avec une certaine tolérance sinon, le résultat du test aura (statistiquement) une chance sur 2 d'être faux. En effet, le dernier chiffre a la même probabilité d'être arrondi par défaut que par excès.

    Concernant l'accumulation des imprésions, c'est un peu plus compliqué que cela.
    Petit problème intellectuel : soient 2 segments de droite, définis par les coordonnées XY de leurs extrémités et qui se coupent.
    Soit I le point d'intersection. On calcule XI et YI, les coordonnées de ce point.
    Quelle est la distance du point I à chacun des deux segments ?

    Vous avez implémenté la triangulation de Delaunay ou vous avez lu de la doc ? Moi, je l'ai implémentée.

    Ce que je veux démontrer avec mon petit exemple est que 2 flottants manifestement inégaux (au sens mathématique) sont testés égaux.

    Votre exemple d'algorithme itératif, convergeant et stable vers l'avant est certainement un très bon exemple, mais je ne traite que de dimension.
    Ceci me rappelle tout une petite anecdote. Vers les années 87-88, les problèmes de performance étaient importants. Or dans notre spécialité l'utilisation de la racine carrée (sqrt) était fréquente, et donc, on cherchait tous les moyens de l'éviter. Il me semble que c'est un bon exemple d'algorithme itératif, convergeant et stable. Dans l'espoir de plaire à mon directeur, j'avais fait un algorithme qui calculait la racine carrée, mais avec la précision nécessaire et non superflue. Cet algorithme était naturellement plus rapide que celui de la librairie (Fortran sur IBM)

Discussions similaires

  1. Probleme de float/double
    Par serebei251 dans le forum Débuter avec Java
    Réponses: 5
    Dernier message: 24/05/2008, 20h25
  2. float, double et arrondi
    Par simla dans le forum Langage
    Réponses: 2
    Dernier message: 25/08/2007, 15h22
  3. Problème de conversion float -> double
    Par Oberown dans le forum C#
    Réponses: 3
    Dernier message: 05/06/2007, 09h23
  4. Comparaison de Float
    Par Rudya dans le forum Langage SQL
    Réponses: 4
    Dernier message: 22/03/2007, 14h19
  5. [Float || Double] positionement d'un point et precision
    Par TabrisLeFol dans le forum Langage
    Réponses: 5
    Dernier message: 29/06/2006, 09h56

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