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 :

Précision et conversion en double


Sujet :

C

  1. #1
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut Précision et conversion en double
    Hello
    Lorsque j'execute ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double ts = atof("0.6");
    printf("ts: %.10f\nts: %.40f\n", ddd, r0, ts, ts);
    J'obtient cela:
    ts: 0.6000000000
    ts: 0.5999999999999999777955395074968691915274
    Bref, je constate qu'il y a une perte énorme (tout est relatif ms ds mon cas c'est énorme) de précision avec la fonction atof!!

    Donc, dans la mesure où je dois récupérer des arguments de la ligne de commande, et les convertir en double, quelqu'un aurait-il une idée de la manière dont je dois m'y prendre afin de garder une présision optimale?

    Merci d'avance

  2. #2
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Le format double est incapable de representer exactement 0.6. Voir les archives, on a explique cela en long et en large. Voir aussi:
    http://docs.sun.com/source/806-3568/ncg_goldberg.html

  3. #3
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    Je sais bien. Le truc c'est que lorsqu'on utilise par exemple le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double ts = 0.6 ;
    printf("ts: %.10f\nts: %.40f\n", ddd, r0, ts, ts)
    On obtient bien une valeur satisfaisante pour ts. Je voulais simplement savoir si il y avais un moyens d'obtenir une meilleur précision que celle obtenue avec atof pour ce que je souhaite faire...

  4. #4
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par vinzzzz
    Je sais bien. Le truc c'est que lorsqu'on utilise par exemple le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double ts = 0.6 ;
    printf("ts: %.10f\nts: %.40f\n", ddd, r0, ts, ts)
    On obtient bien une valeur satisfaisante pour ts. Je voulais simplement savoir si il y avais un moyens d'obtenir une meilleur précision que celle obtenue avec atof pour ce que je souhaite faire...
    J'obtiens:
    ts: 0.6000000000
    ts: 0.5999999999999999777955395074968691915274
    Je ne vois pas pourquoi c'est plus acceptable que ce qu'il y a ci-dessus.

  5. #5
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    Ah tiens moi j'obtient une longue série de 0...

    ts: 0.6000000000
    ts: 0.6000000000000000000000000000000000000000

  6. #6
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 966
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 966
    Par défaut
    Jai,

    De toute manière, pourquoi veux-tu afficher 40 décimales pour un double, alors que ce format donne au mieux 16 (ou 17, je ne sais plus ) chiffres significatifs ?
    (sans oublier que dans la gamme possible, les valeurs représentées exactement sont rares. )

    Et quand tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("ts: %.10f\nts: %.40f\n", ddd, r0, ts, ts)
    ton compilateur ne te signale pas que le nombre d'arguments passés ne correspond pas à ceux demandés dans la chaîne de format ?

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par vinzzzz
    Ah tiens moi j'obtient une longue série de 0...
    Intéressant. Est-ce que tu peux afficher les deux avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void printhex(double d)
    {
       static char tohex[]="0123456789ABCDEF";
       unsigned char* ptr = (unsigned char*)&d;
       int i;
       for (i = 0; i < sizeof d; ++i) {
          putchar(tohex[(ptr[i]>>4) & 0xF);
          putchar(tohex[(ptr[i]>>0) & 0xF);
       }
    }

  8. #8
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    De toute manière, pourquoi veux-tu afficher 40 décimales pour un double, alors que ce format donne au mieux 16 (ou 17, je ne sais plus ) chiffres significatifs ?
    Je sais plus non plus Enfin a vrai dire j'ai jamais su jusqu'a quel nombre de décimal la précision était acceptable en double.

    ton compilateur ne te signale pas que le nombre d'arguments passés ne correspond pas à ceux demandés dans la chaîne de format ?
    J'ai fait un copié collé et j'ai oublié d'enlever les deux variables en trop (ds mon programme elles n'y étaient plus)

    Intéressant. Est-ce que tu peux afficher les deux avec:
    (...)
    J'ai fait tourné le code suivant, en rajoutant ce qui est souligné en gras et qui passait pas a la compilation (je sais pas si c'est ce qu'il fallait):
    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
    void printhex(double d) 
    {
        static char tohex[]="0123456789ABCDEF";
        unsigned char* ptr = (unsigned char*)&d;
        unsigned int i;
        for (i = 0; i < sizeof d; ++i) {
            putchar(tohex[(ptr[i]>>4)] & 0xF);
            putchar(tohex[(ptr[i]>>0)] & 0xF);
        }
        getchar();
    }
    
    double d = 6.0 ;
    printf("d:%.40f\nd:%.20f\n", d, d);
    printhex(d);
    Cela me donne
    d:6.0000000000000000000000000000000000000000
    d:6.00000000000000000000
    
    Enfin ca semble ne pas marcher. La en faisant le copier collé ca donne deux matrices, mais dans ma console j'ai un signe "carreau" (de jeux de carte) et deux F l'un en dessous de l'autres avec un décalage.

    Bref chose encore plus étrange, je fais tourner le même code avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    double d = atof("6.0") ;
    Et j'obtient le même affichage que ci-dessus... Je suis pourtant bien sur le même PC qu'hier soir... Quelque chose m'échape.

  9. #9
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Au moins un problème pour printhex() concernant le placement des crochets:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void printhex(double d) 
    {
        static char tohex[]="0123456789ABCDEF";
        unsigned char* ptr = (unsigned char*)&d;
        unsigned int i;
        for (i = 0; i < sizeof d; ++i) {
            putchar(tohex[(ptr[i]>>4) & 0xF]);
            putchar(tohex[(ptr[i]>>0) & 0xF]);
        }
        getchar();
    }

  10. #10
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    Ok donc avec le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	double d = 6.0 ;
    	double d2 = atof("0.6") ;
    	printf("d:%.40f\nd:%.20f\n", d, d);
    	printhex(d);
    	printf("\nd2:%.40f\nd2:%.20f\n", d2, d2);
    	printhex(d2);
            getchar();
    J'obtient cette fois:
    d:6.0000000000000000000000000000000000000000
    d:6.00000000000000000000
    0000000000001840
    d2:0.5999999999999999777955395074968691915274
    d2:0.59999999999999997780
    333333333333E33F

  11. #11
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Pourquoi utilisez-vous une fois 6.0 et l'autre fois 0.6?

  12. #12
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    Oui en effet j'ai tapé trop vite. C'est pr ca qu'on ne vois pas l'erreur d'arondi je suppose. Avec 0.6, le problème est le même avec atof ou sans finalement...

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 11/05/2006, 08h51
  2. Conversion de doubles
    Par Arnard dans le forum Général Java
    Réponses: 2
    Dernier message: 05/05/2006, 11h04
  3. Decoupage d'une string et conversion en double
    Par TraPpeur dans le forum C++
    Réponses: 2
    Dernier message: 15/02/2006, 23h36
  4. Conversion Réel - Double
    Par gchazelle dans le forum Fortran
    Réponses: 3
    Dernier message: 21/11/2005, 12h37
  5. Conversion en double et notation scientifique
    Par bert24 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 23/09/2005, 13h26

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