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

C++ Discussion :

Imprécision des float et map


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    216
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 216
    Par défaut Imprécision des float et map
    Bonjour,

    Si je crée une map de cette façon : std::map<float, int>, comment la comparaison entre les clefs va elle se faire ?

    Un simple == entre deux float ?

    Merci d'avance...

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    std::map n'utilise pas l'égalité, mais une relation d'ordre. Cela utilisera toujours et uniquement l'opérateur <.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    216
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 216
    Par défaut
    Merci pour ta réponse.

    Quand on utilise la fonction insert de std::map, je comprend parfaitement qu'il n'a pas besoin d'utiliser "==".

    Mais quand on va rechercher un élément comme ceci: maMap[2.5], il doit bien utiliser le "==" ? autrement je voit pas comment il ferait !

  4. #4
    Membre expérimenté Avatar de Ksempac
    Inscrit en
    Février 2007
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 165
    Par défaut
    C'est du a une propriété mathematique toute bete, mais a laquelle on ne pense pas immédiatement : si 2 nombres sont égaux, A < B et B < A renvoient tous les deux FALSE.

    Exemple :

    A = 2, B = 3.
    A < B renvoie TRUE
    B < A renvoie FALSE

    A = 3, B = 2
    A < B renvoie FALSE
    B < A renvoie TRUE

    A = 2, B = 2
    A < B renvoie FALSE
    B < A renvoie FALSE

    C'est une chose qu'il ne faut pas oublier de prendre en compte lorsqu'on surcharge l'opérateur <

    A part ca, meme pour un insert on a besoin de reconnaitre les cas d'egalité, puisque la map doit s'assurer de ne pas avoir de doublon

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    216
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 216
    Par défaut
    Ouais je vois mais donc un map<float, int> ça n'a fonctionnera pas bien dans ce cas à cause de l'imprecision des float alors :

    float a=1.0f;
    float b=2.1f-1.1f;
    maMap[a] = 5;
    maMap[b] = 8;

    Il risque de m'ajouter 2 données différentes dans la map alors que "a" et "b" sont cencé être de la même valeur. C'est bien ça ?

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    L'imprécision dans les calculs sur flottant n'apparait pas au petit bonheur la chance, dans ton calcul a et b contiennent exactement la même chose.
    Cela n'a de risque d'arriver que si tu fais des division. Par exemple il se peut que dans les formules 2.0/3.0 et (1.0/3.0)*2.0 les tout derniers bits utilisés pour représenter la valeur 0.666... soient différents.
    Dans l'absolu, il est vrai que si il y a une différence de ne serais-ce qu'un millionième entre deux flottants map créera deux entrées différentes.
    Si cela te pose un problème, il est possible de personnaliser le foncteur utilisé par map pour faire les comparaisons pour lui imposer une précision limitée (à 1,2,3 chiffres après la virgule par exemple).

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par Ksempac Voir le message
    C'est une chose qu'il ne faut pas oublier de prendre en compte lorsqu'on surcharge l'opérateur <

    A part ca, meme pour un insert on a besoin de reconnaitre les cas d'egalité, puisque la map doit s'assurer de ne pas avoir de doublon
    Etant donné que la std::map utilise seulement l'opérateur plus petit, elle considère que si
    a n'est pas plus petit que b et que
    b n'est pas plus petit que a alors
    a est égal à b...

    Il faut noter que, dans certains cas, cela risque d'apporter quelques bugs originaux (même si je n'ai aucune idée de ce qu'ils peuvent être )

    Comme quoi, il y a parfaitement moyen de ne travailler qu'avec l'opérateur "plus petit"

    Evidemment, il reste le fait que les réels (floats ou doubles d'ailleurs) souffrent d'une imprécision qui est, principalement due à la représentation binaire.

    Comme toute comparaison entre des réels, il faut donc penser à prendre en compte le "décalage" en dessous duquel un nombre reste identique, c'est à dire s'il se trouve entre les X - std::limits<float>::epsilon() et X + std::limits<float>::epsilon() (où X est le nombre utilisé )

    L'un dans l'autre, ca pourrait très bien servir de "théorie" pour créer le foncteur ad-hoc
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    216
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 216
    Par défaut
    Merci pour vos réponses.

    zais_ethael j'aurais logiquement le même raisonnement que toi à propos des float mais :

    1) Dans la FAQ, j'ai vu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    float f1 = 0.1f;
    float f2 = 1.1f;
    float f3 = f2 - f1;
     
    // Version incorrecte ne tenant pas compte des imprécisions
    if (f3 == 1.0f)
    {
        // Pratiquement jamais vrai !
    }
    http://cpp.developpez.com/faq/cpp/?p...ions_flottants

    2) Ce programme m'affiche "2" à l'execution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <iostream>
    #include <map>
    using namespace std;
     
    int main()
    {
    	std::map<float, int> maMap;
     
    	float a=1.0f;
    	float b=2.1f-1.1f;
    	maMap[a] = 5;
    	maMap[b] = 8;
     
    	cout<<maMap.size()<<endl;
     
    	return 0;
    }
    Alors que si je remplace la ligne "float b=2.1f-1.1f;" par "float b=1.0f;",le programme m'affiche "1" !!!

Discussions similaires

  1. [MDA] Tour d'horizon des outils de mapping?
    Par big x dans le forum MDE
    Réponses: 7
    Dernier message: 03/06/2012, 11h35
  2. [Javascript] Précision des float
    Par NicoNours dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 15/03/2006, 09h12
  3. Récupérer des floats à partir d'une string
    Par hamster dans le forum SL & STL
    Réponses: 8
    Dernier message: 09/06/2005, 08h10
  4. Réponses: 9
    Dernier message: 13/04/2005, 22h08
  5. Test if sur des float
    Par Minuit dans le forum Linux
    Réponses: 2
    Dernier message: 26/03/2005, 13h08

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