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 :

condition pas respectée et atof :(


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut condition pas respectée et atof :(
    Bonjour tous,

    je viens vous soumettre un de mes problèmes, j'espère que vous pourrez me débloquer car là je ne sais plus trop quoi faire...

    je vous explique :

    j'ai un fichier texte qui contient des données : "0.1 45.458 0.2 452.5 ...Etc"
    je viens lire ces données ligne par ligne et je stock chacun de ces nombres dans un vecteur de string "vector<string> myNb"

    ensuite je viens faire un conversion de ces composantes de "string" vers "double" avec la commande "atof".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mesDoubles.push_back((atof(myNb[i].c_str())));
    ensuite dans mon code je viens faire un test sur ces nombres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(45.458==mesDoubles[i])
    mon soucis :

    tout ceci fonctionne parfaitement excepté lors du test "if"
    même si dans mon fichier texte j'ai le nombre "45.458" il ne sera transformé par atof en "45.457999999999999999999999"
    et du coup ma condition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(45.458==mesDoubles[i])
    qui devrait être vrai ne l'ai jamais...

    Question :

    du coup, je voudrais savoir comment dois je faire pour que ce test soit vrai lorsque 45.458 est enregistré dans le code en
    temps que "45.457999999999999999999999" ??

    est il possible que "atof" m'enregistre automatiquement la valeur exacte "45.458" ???

    je vous remercie pour l'aide que vous pourrez m'apportez !!!

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    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 186
    Points : 17 126
    Points
    17 126
    Par défaut
    double & float. tout est dit.

    Les nombres flottants ne sont pas une suite de digits après une virgule, mais une suite de bits après une virgule (et avec uniquement 1 avant la virgule), multipliée par une puissance de 2 (ou 10, je n'arrive pas à le retenir).

    Il s'agit d'une somme limitée de puissance négative de 2:

    1 = 1/1 + 0/2 + 0/4 + 0/8 …
    1,5 = 1/1 + 1/2
    45.457999999999999999999999 = des choses...
    45.458 n'est pas possible avec cette écriture.
    renseigne toi sur l'erreur flottante.

    En tout état de cause, l'égalité est impossible entre nombres flottants.

    suppose les fichiers suivants:
    Code autre.h : Sélectionner tout - Visualiser dans une fenêtre à part
    double unite();
    Code autre.c : Sélectionner tout - Visualiser dans une fenêtre à part
    double unite(){return 1.0;}
    Code main.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "autre.h"
    #include <iostream>
    int main(){
        std::cout << ( ( (unite()+0.1)==1.1 ) ? "vrai" : "faux" ) <<std::endl;
    }

    Une fois compilés, on obtient "faux", parce que 1.1 = 1 + 1/16 + 1/32 + 1/256 + 1/512 + ...
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 264
    Points : 725
    Points
    725
    Par défaut
    Bonjour,

    du coup, je voudrais savoir comment dois je faire pour que ce test soit vrai lorsque 45.458 est enregistré dans le code en
    temps que "45.457999999999999999999999" ??
    Tu peux faire la différence entre ta valeur à tester et ta variable et vérifier qu'elle est inférieure à une marge d'erreur (nommée ici EPSILON).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    double temp = (45.458 - mesDoubles[i]);
    if (abs(temp) < EPSILON)
    {
        // Code...
    }
    La valeur que tu choisiras pour EPSILON dépendra de tes besoins en précision.

    est il possible que "atof" m'enregistre automatiquement la valeur exacte "45.458" ???
    Non, comme l'a très bien expliqué Leternel, les unités de calculs à virgule flottante ne comptent pas en décimal, mais en binaire et ne peuvent représenter exactement le nombre 45,458.
    "By and large I'm trying to minimize mentions of D in C++ contexts because it's as unfair as bringing a machine gun to a knife fight." - Andrei Alexandrescu

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    merci de ta réponse leternel mais je n'ai pas tout saisi.... que veux tu dire par pas de test possible sur des flottants ? et sur la différence flottant / double ?

    Precision = voici les étapes de ce bout de code :
    ------------------------------------------------------------
    1°) je lis dans un fichier une base de donnée rentrée par un utilisateur,
    j'enregistre ceci dans des string puis des double (avec atof) et j'ai ma base de donnée de référence.
    2°) je fais des conversions d'unités de ma base de donnée (toujours en double)
    3°) je test si ces nombres qui appartiennent à la base de donnée sont bien égaux au résultat d'un calcul enregistré dans un autre fichier texte.
    ==> je n'ai pas le choix j'ai forcement quelque chose qui peut être différent d'un entier
    ==> comment savoir si un nombre de ma base de donnée existe dans un fichier si je ne peux pas le tester ?

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    Citation Envoyé par Niark13 Voir le message
    Tu peux faire la différence entre ta valeur à tester et ta variable et vérifier qu'elle est inférieure à une marge d'erreur (nommée ici EPSILON).
    OK merci. Je vois ce que tu veux dire

    => par contre est il possible de définir EPSILON egale à l'incertitude de mes variables facilement ?

    => pour des doubles c'est 1e-15 la précision ? je peux donc mettre EPSILON=1e-14 ?

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    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 186
    Points : 17 126
    Points
    17 126
    Par défaut
    tu as un numeric_limits<double>::epsilon(), je crois.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    merci l'éternel ! c'est exactement ce que je cherchais !

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Pour information, std::numeric_limits<float ou double>::epsilon() représente, pour une machine donnée, la plus petite valeur pour le type en question qui ferait que x - epsilon = x = x + epsilon.

    Le problème, c'est que c'est dépendant de l'implémentation

    Ne t'en fais quand meme pas trop, ceci dit : tu as normalement plus que très largement de quoi assurer une plus que correcte pour chaque type envisagé

    Mais ce qui importe surtout, c'est que tu peux, à tout moment, décider d'utiliser une précision moindre que celle indiquée par epsilon : il est toujours possible de dire "voilà, je sais que je dispose de X chiffres derrières la virgule avec epsilon, mais je me contenterai de Y chiffres (ou Y < X )".

    Pour autant, bien sur, que tu aies des raisons d'agir de la sorte

    Et, ceci dit, si tu pars sur l'utilisation d'un double, je présume que c'est parce que tu as besoin d'un maximum de leur précision... Il serait donc dommage d'agir ainsi
    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

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    merci pour ces compléments

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2003] Boucle DO, incrementation si condition pas respectée
    Par jubourbon dans le forum VBA Access
    Réponses: 3
    Dernier message: 17/10/2011, 18h32
  2. Erreur de condition (pas logique)
    Par Khleo dans le forum Langage
    Réponses: 6
    Dernier message: 04/08/2008, 01h43
  3. [MySQL] Les conditions de ma requête ne sont pas respectées
    Par babou54 dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 13/02/2008, 13h28
  4. Le padding n'est pas respecter lors d'un retour a la ligne
    Par pierrot10 dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 07/03/2007, 15h50
  5. Réponses: 2
    Dernier message: 06/04/2006, 10h17

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