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 :

probleme bizarre sur le type double


Sujet :

C++

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 821
    Points : 280
    Points
    280
    Par défaut probleme bizarre sur le type double
    bonjour à tous

    j'aimerais comprendre ceci (en mode de test j'ai fait des calculs en
    dur pour tenter de comprendre ce qu'il se passe sur mes calculs):

    j'ai ceci donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double titi = 0.00;
    titi = (double)(1/49.0) * 6.39693; // le cast n'est pas vraiment necessaire
     
    cout << titi << '?' << (titi==0.13055) << endl;
    je ne comprends pas pourquoi (titi==0.13055) me sort en false (=0!!!)

    ça fait deux heures que je tente de comprendre où je fais mal les choses

    en fait je fais ce test en dur car je me suis rendu compte que après dans
    mon code lorsque je fais
    titi - toto --> ceci me rend différent de 0 alors que toto vaut vraiment 0.13055 (comme titi mais titi a un comportement bizarre et c'est ça que je tente de comprendre)

    si quelqu'un peut m'aider!!!

    merci à tous!!!

    en fait j'ai compris que titi vaut 0.13054959183673469387755102040816 c'est pour cela ; mais je ne comprends pas comment faire pour
    que mon double ne soit pas tronqué!!!

    existe-t-il un long double ou quelque chose du genre?

    merci

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Comme tu l'as vu la représentation semble ne pas être exacte et le nombre calculé possède plus de chiffre non nul après la virgule.
    Pour l'affichage, il faut regarder du côté des manipulateurs de flux (fixed/scientific, setprecision, etc.)
    Exemple à partir de ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
        double titi = 0.00;
        titi = (double)(1/49.0) * 6.39693; // le cast n'est pas vraiment necessaire
     
        std::cout << std::setprecision(20)<<titi << " ? " << (titi==0.13055) << std::endl;
     
     
        return 0;
    }

  3. #3
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Citation Envoyé par Garra Voir le message
    existe-t-il un long double ou quelque chose du genre?
    Tout à fait !
    Selon l'architecture, ou le compilateur, je crois même qu'il existe un « long long double ».

    Ceci dit, je ne suis pas sûr qu'augmenter la précision résolve ton problème…

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Il est impossible techniquement de ne pas tronquer un double. Pour représenter tous les nombres de l'ensemble réel entre 0 et 1, il faudrait un système permettant de stocker un nombre infini de combinaison dans un espace fini. Tu comprendras aisément que ce n'est pas possible.

    Je te conseille de lire cet article de wikipedia sur le sujet. Tu y trouveras certaines explications concernant la précision des nombres en virgule flottante. Pour une discussion plus technique, cet article est un article de référence.

    Un point important est que, sauf cas exceptionnel, on ne peut pas comparer deux nombres flottants entre eux. Une opération qui mathématiquement est valide ne donne pas nécessairement un résultat valide à cause des limitations liées à la précision (et au mode de calcul) en virgule flottante. Certains nombres peuvent être représentés de manière exacte (0.0, 1.0, et de nombreux autres) mais pas tous (0.1 n'admet aucune représentation, que ce soit en float, double ou long double; 0.01 non plus, ce qui fait que 0.1*0.1 != 0.01). Déjà, il est censé de penser que seuls les rationnels peuvent l'être (nombre rationnel = P/Q, ou P et Q sont des entiers) : inutile de tenter de représenter pi sur un nombre fini de décimales. De plus, tous les rationnels ne peuvent pas être représentés (1/3 admet un nombre infini de décimales).

    Ensuite, pour qu'un nombre soit représentable, il faut qu'il admette une représentation de la forme (1+0,X)*2^n. Plus exactement :



    Enfin, de manière évidente, il faut que le nombre de bit nécessaire au stockage du nombre soit suffisant. Sur un double, on a droit à (environ) 16 chiffres significatifs (en fait, 15 ou 16, cela dépends des nombres considérés). Du coup, il est impossible de représenter la valeur suivante : 123456789,123456789 (18 chiffres significatifs).

    Cette notion de chiffres significatifs pose des problèmes lors de l'addition de nombres d'ordre de grandeur très différents : 123456789123456789 + 0,1 ne peut être effectuée, car cela supposerait de stocker un résultat avec 19 chiffres significatifs (3 de trop).

    Enfin bref, tout ça pour dire qu'utiliser les nombres en virgule flottantes n'est pas, loin s'en faut, d'une grande simplicité. Comme toujours, il faut savoir ce que l'on fait afin de pouvoir proposer une implémentation correcte de notre besoin. Accessoirement, cette implémentation ne passe pas nécessairement par un nombre flottant : si ceux si sont utiles pour de nombreuses opérations, ils peuvent être avantageusement remplacé par des nombre en virgule fixe (cad des entiers auquel on affecte un coefficient implicite). Un entier de 64 bits permet de stocker 17 à 18 chiffres significatifs (selon qu'on prenne en compte le signe ou non), ce qui est supérieur à ce qu'offre un nombre de même taille en virgule flottante. Si on veut de la précision et que le domaine de définition de nos valeurs ne s'étends pas trop, ça peut être une alternative tout à fait viable.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 821
    Points : 280
    Points
    280
    Par défaut
    Ah, toutes ces réponses c'est génial

    c'est formidable, je vais regarder tout ça en détail

    en réalité ces valeurs sont pour comparer les distances entre vecteurs
    et je trouvais bizarre que le même vecteur ne me donne pas 0 dans la différence.
    (une des valeurs est calculée et l'autre vient dans un fichier)

    Après, si en utilisant une precision plus correcte pour un double, je
    trouve une différence très très petite, ce n'est pas grave car de toutes façons ces deux vecteurs seront considerés comme étant les plus proches;
    donc dans mon cas c'est bon.

    je regarderai ceci en détail, c'est super utile merci encore

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 821
    Points : 280
    Points
    280
    Par défaut
    une autre petite question:

    je suis sur vista 64bits; donc normalement je peux utiliser par exemple des nombres avec plus de précision ; comme un long double par exemple.

    mais est-ce que ceci concerne la compil ou aussi l'environnement d'excution.

    si mon programme compilés sur windows 64bits, est executé sur windows 32bits, je devrais rencontrer des problèmes non?

    merci encore à tous

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Garra Voir le message
    une autre petite question:

    je suis sur vista 64bits; donc normalement je peux utiliser par exemple des nombres avec plus de précision ; comme un long double par exemple.
    Les réels (double et long double) sont déjà en général codés sur plus de 32 bits (souvent 64 bits pour double et 96 bits je crois pour long double) que l'OS soit 32 ou 64 bits.

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Garra Voir le message
    Après, si en utilisant une precision plus correcte pour un double, je
    trouve une différence très très petite, ce n'est pas grave car de toutes façons ces deux vecteurs seront considerés comme étant les plus proches;
    donc dans mon cas c'est bon.
    C'est d'ailleurs la seule "bonne" manière de comparer deux réels (float ou double) : tu fais la différence et tu regardes si le résultat est inférieur ou égal à un epsilon donné que tu fixes à l'avance selon le niveau de précision nécessaire.
    Find me on github

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 821
    Points : 280
    Points
    280
    Par défaut
    super donc je suis dans la bonne voie
    grâce à vous tous et à vos conseils!!!!

    merci encore

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Et pour une discussion sur la valeur d'epsilon (parce que, oui, même ça ce n'est pas trivial), voir ce document.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    C'est d'ailleurs la seule "bonne" manière de comparer deux réels (float ou double) : tu fais la différence et tu regardes si le résultat est inférieur ou égal à un epsilon donné que tu fixes à l'avance selon le niveau de précision nécessaire.
    en sachant qu'il est toujours préférable d'utiliser une erreur relative plutôt qu'une erreur absolue. Maintenant, si la valeur exacte est proche de 0... on peut encore se tirer les cheveux...

Discussions similaires

  1. Quelques précisions sur le type double
    Par darkwall_37 dans le forum Débuter
    Réponses: 10
    Dernier message: 10/11/2009, 13h51
  2. [PDO] Probleme bizarre sur requête
    Par kanabzh29 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 25/06/2008, 15h35
  3. Probleme bizarre sur FTP
    Par Kahlyv dans le forum Sécurité
    Réponses: 2
    Dernier message: 26/03/2007, 19h03
  4. Probleme bizarre sur relief d'un bouton
    Par Kara dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 21/07/2005, 11h32
  5. Réponses: 3
    Dernier message: 17/05/2004, 17h28

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