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 :

Conversion incorrecte avec atof ou strtod


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Conversion incorrecte avec atof ou strtod
    Bonjour,

    Voilà mon problème :
    - Ma chaine szParam (char [500]) contient "5000000000000039" (avec \0 à la fin). (pour info il y a 13 "0")
    - Je dispose d'une variable dCodePgmTri (double) ; (petite précision au cas où : cette variable fait partie d'une structure et j'utilise un tableau de cette structure)
    - Je fais dCodePgmTri = atof (szParam)

    Je compile mon programme sous W2000 (avec Visual C++ 6.0) et sous Unix HP (via gcc).
    Sous W2000, la conversion de ma valeur fonctionne parfaitement, par contre sous Unix HP, la conversion me renvoie "5000000000000040" !!

    Je ne dépasse pourtant pas la valeur max d'un double (qui est beaucoup, beaucoup plus grande...j'ai d'ailleurs fait un affichage ecran de DBL_MAX pour m'en assurer).
    J'ai constaté que si je mets "38" à la place de "39" (je ne répète pas ici les chiffres qui précèdent), j'obtiens la bonne valeur ; avec 40 j'obtiens 40 et avec 41 j'obtiens aussi 40. Par contre avec 9941 j'obtiens 9920 !

    J'ai essayé avec strtod et j'obtiens les mêmes résultats toujours corrects sous W2000 mais parfois incorrect sous Unix...

    Ce programme tourne depuis un petit moment et cette erreur n'avait jamais été détectée avant qu'on ne tombe sur la valeur "50...39"

    Alors si quelqu'un a une idée, je suis preneur...

    Merci d'avance.
    Sebastien "quelque peu déboussolé sur ce coup-là"

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    Voilà mon problème :
    - Ma chaine szParam (char [500]) contient "5000000000000039" (avec \0 à la fin). (pour info il y a 13 "0")
    - Je dispose d'une variable dCodePgmTri (double) ; (petite précision au cas où : cette variable fait partie d'une structure et j'utilise un tableau de cette structure)
    - Je fais dCodePgmTri = atof (szParam)
    Cette fonction est obsolète depuis ... 1989! Préférer strtod()...
    Je compile mon programme sous W2000 (avec Visual C++ 6.0) et sous Unix HP (via gcc).
    Sous W2000, la conversion de ma valeur fonctionne parfaitement, par contre sous Unix HP, la conversion me renvoie "5000000000000040" !!
    C'est grave ? Ca fait une précision de 1.99E-14 %, je m'en contente...

    Visiblement tu ne sait pas ce que sont les nombres à virgule flottantes... En gros, se sont des nombres codés "signe, mantisse, exposant". La gamme est très large, mais la précision est évidemment limitée... Il est donc tout à fait normal que les chiffres de poids faibles soient imprécis. Je te renvois à ton Wiki préféré pour les détails...
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Encore et toujours le problème de représentation des nombres réels en machine.

    Le langage C n'impose rien quand à la représentation interne des nombres à virgules flotantes, c'est pour cela que tu as cette différence entre les deux platteformes.

    Mais étant donné que l'écart est faible, tu peux peut être t'en contenter ...

  4. #4
    Candidat au Club
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Conversion incorrecte avec atof ou strtod
    Alors j'utilise peut-être pas le bon type et je n'ai pas du totu comprendre sur les types à virgules flottantes.

    En fait ma valeur correspond à un code identifiant (donc un nombre entier) issue d'une base de données (numeric 18 ), il est donc important que la conversion soit exacte.

    Mais alors si je ne dois pas prendre des doubles, quelle type (et quelle fonction de conversion associée) dois-je utiliser pour stocker un nombre entier pouvant avoir jusqu'à 18 chiffres ?

  5. #5
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Le problème est qu'avec le format double le plus répandu (et je doute fort qu'HP ne l'utilise pas -- si j'ai bonne mémoire, HP a des particularité sur la représentation des NaN mais rien de plus), les entiers positifs inférieurs ou égal à 9007199254740992 sont représentables exactement. Et 5000000000000039 en fait partie. Cela vaut la peine d'investiger.

    Comment fais-tu tes affichages?

    Si tu optiens le même nombre d'une autre manière qu'avec strtod (par exemple (double)500000*(double)100000000+(double)39) est-ce qu'il y a le même problème?

    Est-ce que ton printf reconnait %a et que donne l'affichage avec?
    (ca devrait être 0x1.1c37937e08027p+52)

    Si tu manipules beaucoup des flottants, tu as intérêt à te renseigner plus sur eux, car ce sont des bêtes particulières.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  6. #6
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Si ton compilateur supporte la norme C99, tu peux peut-être utiliser un long long, et même un unsigned long long (si tu n'a pas de code négatif). Ce type est une nouveauté de la norme et garantie un nombre sur 64 bits.

    Pour info : 2^64 = 18 446 744 073 709 551 616

    Avec ce type tu as 19 décimales exploitables.

    En général, les flottants sont codé sous le format IEEE 754, mais ce n'est pas le cas partout et il n'y a pas de norme entre les architectures.

  7. #7
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    En fait ma valeur correspond à un code identifiant (donc un nombre entier) issue d'une base de données (numeric 18 ), il est donc important que la conversion soit exacte.
    Les flottants ne sont pas la solution alors.

    Mais alors si je ne dois pas prendre des doubles, quelle type (et quelle fonction de conversion associée) dois-je utiliser pour stocker un nombre entier pouvant avoir jusqu'à 18 chiffres ?
    long long va jusque 9223372036854775807 (donc tu as tes 18 chiffres si je ne me suis pas trompé), unsigned long long jusque 18446744073709551615 (ce qui fait 19 chiffres).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    En fait ma valeur correspond à un code identifiant (donc un nombre entier) <...> quelle type (et quelle fonction de conversion associée) dois-je utiliser pour stocker un nombre entier pouvant avoir jusqu'à 18 chiffres ?
    Des entiers. [C99] long long ou unsigned long long, par exemple.
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Candidat au Club
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Conversion incorrecte avec atof ou strtod
    Ok, demain au boulot je testerai donc le "unsigned long long" pour voir si ça marche.

    En espérant que mes compilateurs supporte la norme C99. Je rappelle que sous Windows j'utilise le compilateur de Visual C++ 6.0 et sous Unix j'utilise gcc (je crois que c'est la version 3.2 mais je dois vérifier...)

    Et sinon c'est quoi la fonction de conversion en lieu et place de "strtod" ?

    Merci de votre aide. J'apprends plein de chose sur ce coup-là...

  10. #10
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    je ne connais pas les options de VC++ mais pour gcc, tu peux tester avec l'option suivante :

    -std=c99 , si tu n'a pas d'erreur, c'est que ta version devrai supporter la norme (pas entièrement mais au moins long long y est.)

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    En espérant que mes compilateurs supporte la norme C99. Je rappelle que sous Windows j'utilise le compilateur de Visual C++ 6.0
    N'est pas C99; mais a une extension int64 ou un truc comme ça... Détails sur le forum "Développement Windows".
    et sous Unix j'utilise gcc (je crois que c'est la version 3.2 mais je dois vérifier...)
    gcc supporte (partiellement) C99 depuis la version 3.x. La dernière version de gcc est 4.x.
    Et sinon c'est quoi la fonction de conversion en lieu et place de "strtod" ?
    [C99] strtoll() et strtoull()
    Pas de Wi-Fi à la maison : CPL

  12. #12
    Candidat au Club
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Bonjour,

    Merci pour toutes ces infos. Finalement pour rester plus ouvert (si par exemple mes identifiants devenaient un jour des numeric 20 ou plus) et sachant que je ne fais donc aucune opération sur ces valeurs mais uniquement des tests d'égalité, je vais reste en "char" et je ferai mes comparaisons octect par octet.

    En fait au départ je croyais juste gagner du temps en faisant mes tests d'égalité avec des numériques plutôt ques des char mais bon il ne doit pas y avoir une grande différence...

  13. #13
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Dans ce cas, tu peux peut être utiliser memcmp

  14. #14
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    Finalement pour rester plus ouvert (si par exemple mes identifiants devenaient un jour des numeric 20 ou plus) et sachant que je ne fais donc aucune opération sur ces valeurs mais uniquement des tests d'égalité, je vais reste en "char" et je ferai mes comparaisons octect par octet.
    Si ce sont des chaines de caractères, strcmp()...
    Pas de Wi-Fi à la maison : CPL

  15. #15
    Candidat au Club
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Bonsoir,

    Me revoilà car d'autres soucis m'ont détourné du sujet...

    Bon j'ai essayé en passant par des chaines mais ça a considérablement augmenté mes temps de traitements sur de gros volumes de données. Donc je repars sur des numériques...

    Alors, sauf erreur de ma part on a :
    sous Windows
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _int64 ou unsigned __int64
    printf ("%I64i ou %I64u"...
    _atoi64
    sous Unix
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    long long ou unsigned long long
    printf ("%lli ou %llu"...
    Mais quel est l'équivalent de _atoi64 sous Unix ? J'ai cherché partout mais je n'ai pas trouvé (je suppose que je suis un mauvais chercheur...)
    Et quel est l'équivalent, sous Unix et sous Windows, pour des unsigned ?

    Merci d'avance.

    PS : quelqu'un avait mentionné les fonctions strtol et strtoul mais ça ne fonctionne pas avec des entiers 64bits.

  16. #16
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Peut être strtoll :

    http://manpagesfr.free.fr/man/man3/strtol.3.html

  17. #17
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Conversion incorrecte avec atof ou strtod
    Citation Envoyé par sber74
    Mais quel est l'équivalent de _atoi64 sous Unix ?
    strtoll() et strtoull()
    Pas de Wi-Fi à la maison : CPL

Discussions similaires

  1. Conversion nombre entier incorrecte avec parseInt
    Par zouetchou dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 29/12/2012, 18h50
  2. Réponses: 5
    Dernier message: 02/07/2006, 19h37
  3. Réponses: 5
    Dernier message: 16/02/2006, 00h48
  4. Affichage incorrect avec une JScrollPane
    Par tck-lt dans le forum Agents de placement/Fenêtres
    Réponses: 23
    Dernier message: 04/08/2005, 11h07
  5. Réponses: 2
    Dernier message: 03/08/2005, 00h39

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