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 :

Egalité entre flottants


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Février 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 27
    Par défaut Egalité entre flottants
    Bonjour,

    Je me pose quelques questions sur les calculs et comparaisons de flottants et sur l'emploi de la macro :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define FLOAT_EQ(_x, _y, _epsi) ((((_y) - (_epsi)) < (_x)) && ((_x) < ((_y) + (_epsi))))
    avec _epsi généralement égal à à FLT_EPSILON qui est défini dans float.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */
    Or, d'après moi, des que x devient un peu grand, le flottant x-FLT_EPSILON (resp x+FLT_EPSILON) est égal à x. Dans le code suivant, a==x
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        float x = 3;
        float a = x - FLT_EPSILON;
    pourtant, quand on compare directement x - FLT_EPSILON et x, il sont bien differents :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        bool eq1 = x - FLT_EPSILON < x;
    et FLOAT_EQ(x, 3, FLT_EPSILON) vaut bien true.

    J'ai ma petite idée sur la raison mais j'aimerais en être sûr.
    Le c++ prévoit-il que tous les calculs et comparaisons de flottans (float, double,...) soient réalisés sur des réels (10 bytes) ou bien est-ce dû à l'implémentation de mon compilo(VC8)?

    Et vous, comment testez vous l'égalité entre deux flottants?

    Merci pour vos réponses

  2. #2
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Hello,

    Les égalités entres flottants, ça toujours été un sujet délicat.

    Citation Envoyé par damiengif Voir le message
    Or, d'après moi, des que x devient un peu grand, le flottant x-FLT_EPSILON (resp x+FLT_EPSILON) est égal à x. Dans le code suivant, a==x
    C'est "normal", plus le nombre est grand plus la précision diminue, pour tout nombre >= 2, x + FLT_EPSILON == x et x == x - FLT_EPSILON.

    Il n'y à pas de solutions miracle, soit le comportement te convient, soit tu aggrandi epsilon (mais dans ce cas de petits nombres pourront être considérés comme égaux alors qu'ils ne le sont pas).

    Note que la STL propose cet epsilon, pas besoin de le redéfinir.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::numeric_limits<float>::epsilon();

  3. #3
    Membre averti
    Inscrit en
    Février 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 27
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    pour tout nombre >= 2, x + FLT_EPSILON == x et x == x - FLT_EPSILON.[/code]
    Pas tout à fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        float x = 3.; 
        float y = x + std::numeric_limits<float>::epsilon();
        bool eq1 = ( x == x + std::numeric_limits<float>::epsilon() );     // faux
        bool eq2 = ( x == y );                                                         // vrai
        bool eq3 = ( y == x + std::numeric_limits<float>::epsilon() );     // faux

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Personnellement, je traite ce problème de la façon suivante:
    Soit les valeurs traitées ont des dimensions homogènes, par exemple des données du type géographique, alors j'ai adopté le type long, c'est à dire que je dispose de 9 chiffres significatifs, et je me fixe une unité de base, 3 par exemple, et la position de la virgule est une donnée de ma base de données. Autrement dit, dans le cas général, je ne compare pas des flottants mais des entiers.
    Il peut arriver que j'ai effectivement à comparer des flottants, alors, je compare la valeur absolue de leur différence avec un epsilon.
    Il ne me viendrait pas à l'idée d'ajouter (ou de soustraire) un epsilon à un nombre dont un ne connait pas l'ordre de grandeur.

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    FLT_EPSILON est l'écart entre 1 et la première valeur flottante suivante.
    avec 3, la précision n'est déjà plus la même.

    Plutôt que FLT_EPSILON, je suggère d'utiliser std::numeric_limits<float>::epsilon() (dans <limits>)

    Regarde cette référence pour une explication et un exemple d'usage.

    En gros, il faut multiplier l'epsilon par le plus grand des nombres à comparer. (et un petit détail de plus, regarde l'exemple)

Discussions similaires

  1. Egalité entre objet
    Par la debutante dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 27/08/2007, 22h47
  2. Egalité entre BuffuredImage
    Par ArkSeth dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 20/07/2007, 12h34
  3. Egalité entre deux champs NULL ?
    Par AyaGizmo dans le forum SQL
    Réponses: 2
    Dernier message: 08/06/2007, 11h42
  4. .NET C# Egalité entre 2 instances
    Par mow dans le forum Windows Forms
    Réponses: 6
    Dernier message: 10/08/2006, 09h38
  5. [C++.NET] Egalite entre datatables
    Par raboin dans le forum VC++ .NET
    Réponses: 5
    Dernier message: 06/06/2006, 15h59

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