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 :

Problème d'arrondi


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut Problème d'arrondi
    Bonjour

    Je suis confronté à un problème d'arrondi de nombres flottants en C/C++:
    J'ai besoin de faire des conversions double->string et vice-versa.
    Le problème étant que ces conversions ne semblent pas tout à fait réversibles; en effet, si je fais:

    string1->double->string2

    à l'arrivée, string1 et string2 ne sont pas forcément identiques !

    la raison en est que atof() donne un résultat approximatif;

    exemple: atof ("121.1") retourne 121.09999999999999 et non 121.1 comme on pourrait s'y attendre.

    et si je fais la conversion à la main (sans utiliser atof() donc), je ne parviens pas non plus à obtenir quelque chose de réversible à cause de bizarreries dans les calculs en doubles flottants du style:

    1.0 * 0.1 = 0.10000000000000001 ...

    Voilà, toute suggestion pour faire des conversions de ce type réversibles serait la bienvenue. Merci.

    Je précise que je suis sous VC7.1, bien que je doute que ce soit le compilateur la cause de tout ça...
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  2. #2
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Pourquoi est-ce que tu utilises 'atof' ? Préfère des fonctions comme sscanf ou strtod...

    Exemple avec sscanf :
    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
    18
    19
    20
     
    #include <stdio.h>
     
    int main (void){
     
      const char   *s = "121.5";
      char          t[6] = {0};
      double        f;
     
      /* conversion chaine -> double */
      sscanf (s, "%lf", &f);
      /* faire les tests de retour de sscanf... */
     
      /* conversion double -> chaine */
      sprintf (t, "%f", f);
     
      fprintf (stdout, "s = %s\nf = %f\nt = %s\n", s, f, t);
     
      return 0;
    }
    Exemple avec strtod :
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main (void){
     
      const char   *s = "121.5";
      char          t[6] = {0};
      double        f;
     
      f = strtod (s, NULL);
      sprintf (t, "%f", f);
     
      fprintf (stdout, "s = %s\nf = %f\nt = %s\n", s, f, t);
     
      return 0;
    }
    Software becomes slower faster than hardware becomes faster
    [size=1]
    http://xrenault.developpez.com

  3. #3
    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
    Le problème est intrinsèque à l'utilisation de nombres en virgule flottantes. Ceux-ci ne permettent de représenter exactement que des nombres de la formesoù m et e sont des entiers, et ^ note l'exponentiation.

    0.1 n'étant pas de cette forme est remplacé par le nombre le plus proche de 0.1 possible ayant cette forme, mais évidemment le résultat n'est pas celui qu'on aurait obtenu si 0.1 était représentable.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Pourquoi est-ce que tu utilises 'atof' ? Préfère des fonctions comme sscanf ou strtod...
    Parce que atof() semble approprié !
    De toute façon, je viens de faire le même type de test avec scanf() et strtod() et les résultats sont les mêmes.

    En fait, une des difficultés vient aussi de ce que le debugger du Visual 7 formate les floats et les doubles dans la fenêtre des variables différemment de ce qu'on obtient avec un %f ou %lf dans les fonctions de type printf(); et donc les arrondis sont différents

    Par ailleurs, je viens de découvrir que la promotion de float en double introduit des décimales parasites, ce qui ne fait que contribuer un peu plus à la confusion.
    Le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      float  toto = 121.512f;
      double titi = 121.512;
      double tutu = toto;
      printf (" toto = %f \n titi = %.9lf \n tutu = %.9lf \n", toto, titi, tutu);
    donne ça dans la console:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     toto = 121.512001 
     titi = 121.512000000 
     tutu = 121.512001038
    Soit 3 valeurs différentes en sortie pour une valeur unique en entrée !

    On doit néanmoins pouvoir s'en sortir en évitant de mixer les floats et les doubles et en limitant la précision en dessous de la limite théorique des doubles (15 décimales si je ne m'abuse).

    A moins qu'il existe une astuce pour éviter l'introduction de décimales parasites dans la promotion float->double et qu'il soit possible de faire en sorte que 1 * 0.1 = 0.1 et non 0.10000000000000001 !?

    Si quelqu'un a les idées claires sur ces problématiques, merci d'en faire profiter les ignorants comme moi
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  5. #5
    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
    Citation Envoyé par rigobert
    Si quelqu'un a les idées claires sur ces problématiques, merci d'en faire profiter les ignorants comme moi
    Il faut savoir que
    • La représentation interne des flottants est toujours une approximation.
    • Le type double est plus précis que le type float.
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Le type double est plus précis que le type float.
    Certes, mais si on fait une analogie avec les entiers, un char d'une valeur de 100 lorsqu'il est converti/promu en int fait toujours 100 et non 101 ou 99 !

    En d'autres termes, il serait logique que la conversion d'un float de 121.512 en double donne 121.51200000000000 et non 121.51200103845 !
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  7. #7
    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
    Citation Envoyé par rigobert
    Le type double est plus précis que le type float.
    Certes, mais si on fait une analogie avec les entiers, un char d'une valeur de 100 lorsqu'il est converti/promu en int fait toujours 100 et non 101 ou 99 !

    En d'autres termes, il serait logique que la conversion d'un float de 121.512 en double donne 121.51200000000000 et non 121.51200103845 !
    Quels sont les mots que tu ne comprends pas dans
    La représentation interne des flottants est toujours une approximation.
    Il ne faut pas chercher des analogies ou de la logique là où il n'y en a pas. Renseigne toi sur la façon dont sont codés les flottants (doc de ton compilateur, car non standard en C) et tu verras que c'est un autre monde.

    Exemple de normalisation des flottants (IEEE-754) dans le monde scientifique (malheureusement pas imposé en C pour des raisons historiques)

    http://www.psc.edu/general/software/packages/ieee/ieee.html
    Pas de Wi-Fi à la maison : CPL

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par rigobert
    Le type double est plus précis que le type float.
    Certes, mais si on fait une analogie avec les entiers, un char d'une valeur de 100 lorsqu'il est converti/promu en int fait toujours 100 et non 101 ou 99 !

    En d'autres termes, il serait logique que la conversion d'un float de 121.512 en double donne 121.51200000000000 et non 121.51200103845 !
    Quels sont les mots que tu ne comprends pas dans
    La représentation interne des flottants est toujours une approximation.
    J'avais bien compris tous les mots, inutile d'être désagréable.

    Ton affirmation même si elle est claire n'est pas la réponse à toutes les questions;
    entre autres, elle ne va pas à l'encontre de l'idée que dans le monde approximé et imparfait des flottants il puisse quand même y avoir un minimum de cohérence entre les petits (32-bit), les moyens (64-bit) et les grands (80-bits) flottants, de même qu'il existe une cohérence entre les chars, les shorts, les longs et les longlongs dans le monde des entiers.

    Mais puisque c'est une aberration de penser ça et mal de l'exprimer, pardon.

    Merci quand même pour le lien.
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  9. #9
    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
    En d'autres termes, il serait logique que la conversion d'un float de 121.512 en double donne 121.51200000000000 et non 121.51200103845 !
    Non, il n'y a pas de logique, c'est du à la représentation des réels en mémoire.

    121.51200103845 est le plus proche nombre que ton ordinateur a pu trouvé pour 121.512, c'est tout.

    Alors ça ne te parais pas logique, mais un ordinateur ne fonctionne pas comme un humain, il faut en être conscient.

    Emmanuel te l'a dis, les réels en mémoire ne sont que des approximations.

    Si tu veux travailler avec des réels d'une façon presque identique à celle que tu crois être logique, il te faut utiliser une bibliothèque de fonction du style de gmp, mais tu ne trouveras rien dans le langage C directement.

  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
    il puisse quand même y avoir un minimum de cohérence entre les petits (32-bit), les moyens (64-bit) et les grands (80-bits) flottants, de même qu'il existe une cohérence entre les chars, les shorts, les longs et les longlongs dans le monde des entiers.
    La représentaton d'un nombre réel, est beaucoup plus compliquée à réaliser que celle des entiers.

    Admettons qu'il faille que tu représentes un nombre entier entre 0 et 65535, c'est simple, puisque tu as au maximum 65536 possibilités. Dans ce cas, avec 16 bits, tu peux représenter tous ces entiers.

    En revanche, si tu dois coder tous les réels entre 0 et 10, tu ne peux pas puisqu'il y a une infinité de nombre, il faut donc trouver un compromis et trouver des "équivalences" (j'aime pas le mot mais j'ai pas mieux), en gros ça veut dire que 1.51 sera considéré comme égal à 1.512, c'est une question de précision.

    Il existe une multitude de codage différents pour coder les réels sur un nombre limité de bits. Le codage IEEE 754 en est une.

    Cette norme utilise le système signe exposant mantisse, si tu veux plus d'info, utilise google, il y a énormément de doc dessus.

    Mais dans cette norme, tu as plusieurs variantes, notament l'IEEE 754SP (pour simple precision) et l'IEEE754DP (pour double précision), la différence se situant aux nombre de bits affectés à chacune des "parties" de ton nombre (ie: plus de bits au total pour le DP et une répartition différente de l'exposant et la mantisse). Cela entraine donc une différence de précision entre les types, et la pseudo "incohérence" dont tu parles.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Citation Envoyé par PRomu@ld
    121.51200103845 est le plus proche nombre que ton ordinateur a pu trouvé pour 121.512000000, c'est tout.
    Siouplait les gars, lisez les posts avant de répondre.

    le nombre 121.512 est parfaitement représentable en double flottant:

    Le code suivant:

    float toto = 121.512f;
    double titi = 121.512;
    double tutu = toto;
    printf (" toto = %f \n titi = %.9lf \n tutu = %.9lf \n", toto, titi, tutu);

    donne ça dans la console:

    toto = 121.512001
    titi = 121.512000000
    tutu = 121.512001038
    Comme tu peux le constater, seul titi a une valeur correcte.
    Donc, je me répète, c'est bien un problème de conversion, pas de représentation.
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  12. #12
    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
    Citation Envoyé par rigobert
    le nombre 121.512 est parfaitement représentable en double flottant:
    du moins sur ton implémentation.
    Comme tu peux le constater, seul titi a une valeur correcte.
    Donc, je me répète, c'est bien un problème de conversion, pas de représentation.
    Oui, il y a 2 problèmes. La représentation interne et la conversion.
    (merci de m'épargner les titi et les toto...)
    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
    18
     
    #include <stdio.h>
     
    int main (void)
    {
       float a = 121.512;
       double b = 121.512;
       double c = a;
     
    #define PRT(x)\
       printf ("%3s = %.20f\n", #x, x);
     
       PRT (a);
       PRT (b);
       PRT (c);
     
       return 0;
    }
    Chez moi (mingw / Win XP) ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      a = 121.51200103759766000000
      b = 121.51200000000000000000
      c = 121.51200103759766000000
    Pas de Wi-Fi à la maison : CPL

  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
    Siouplait les gars, lisez les posts avant de répondre.
    , cool !

    le nombre 121.512 est parfaitement représentable en double flottant:
    T'es sur de ça ? Quel est alors le mode de représentation qui permet de représenter un réel dans une machine dont la mémoire est finie ?

    Comme tu peux le constater, seul titi a une valeur correcte.
    Depuis quand un affichage sert de preuve ?

    Donc, je me répète, c'est bien un problème de conversion, pas de représentation.
    Non, c'est un problème de représentation ou plutôt de changement de représentation.

    Et encore, je n'en serai pas si sur.

    regarde la valeur de toto lors de l'affichage : 121.512001, ce n'est donc pas 121.512, donc, ce que tu converti c'est 121.512001 et pas 121.512 ...

  14. #14
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par rigobert
    Citation Envoyé par PRomu@ld
    121.51200103845 est le plus proche nombre que ton ordinateur a pu trouvé pour 121.512000000, c'est tout.
    Siouplait les gars, lisez les posts avant de répondre.

    le nombre 121.512 est parfaitement représentable en double flottant:

    Le code suivant:

    float toto = 121.512f;
    double titi = 121.512;
    double tutu = toto;
    printf (" toto = %f \n titi = %.9lf \n tutu = %.9lf \n", toto, titi, tutu);

    donne ça dans la console:

    toto = 121.512001
    titi = 121.512000000
    tutu = 121.512001038

    OUi, sur ton implementation, 121.152 est "parfaitement representable" dans un double (le titi est donc affiche correctement).
    Par contre il n'est l'ai pas dans un float, donc il devient 121.512001 dans toto.
    Concernant tutu, tu l'affecte a la valeur de toto (soit 121.512001) mais cette valeur n'est pas representable dans un double, le nombre est donc arrondit a la plus proche valeur representable dans un double (ie chez toi 121.512001038).

    Le comportment que tu observes est bien lie a la representation approchee des nombres reels (et non n probleme de conversion) et est tout a fait normal.

    EDIT : le "parfaitement representable" est volontairement entre guillemets puisque tu force l'affichage sur 9 digits, donc il n'y a une certitude que sur ces 9 chiffres.

  15. #15
    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
    Citation Envoyé par rigobert
    Citation Envoyé par PRomu@ld
    121.51200103845 est le plus proche nombre que ton ordinateur a pu trouvé pour 121.512000000, c'est tout.
    Siouplait les gars, lisez les posts avant de répondre.
    S'il te plait, comprends les messages avant de considérer qu'on ne t'a pas lu.

    le nombre 121.512 est parfaitement représentable en double flottant:
    J'ai quelques doutes. Je ne vois pas pourquoi une implémentation aurait des doubles décimaux et des float binaires sans compter que ce n'est pas permis par la norme (il n'y a que FLT_RADIX, pas des variantes pour les différentes tailles) et que je ne connais pas un ordinateur récent avec des flottants décimaux (bien que ça ne m'étonnerait pas qu'IBM en resorte).

    Dans tous les cas, le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      float  toto  = 121.512f;
      double titi = 121.512;
      double tutu = toto;
      printf (" toto = %f \n titi = %.9lf \n tutu = %.9lf \n", toto, titi, tutu);
    ne suffit pas pour le montrer. Tu montres juste qu'un double est capable de représenter 121.512 avec au moins 9 chiffres de précision, ce qu'on savait déjà. Il faut afficher un peu plus de chiffres. Chez moi le programme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #include <float.h>
     
    int main()
    {
       float toto = 121.512f;
       double titi = 121.512;
       double tutu = toto;
       printf (" toto = %f \n titi = %.9lf \n tutu = %.9lf \n", toto, titi, tutu);
       printf (" titi = %.30lf\n", titi);
       printf (" FLT_RADIX = %d\n", FLT_RADIX);
       return 0;
    }
    affiche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     toto = 121.512000 
     titi = 121.512000000 
     tutu = 121.512000084 
     titi = 121.512000000000000010658141036401
     FLT_RADIX = 2
    et on voit bien que titi n'est pas exactement 121.512 (et que la base des flottants est bien 2). (Colle pour les experts, qu'est-ce que j'utilise?)

    Donc, je me répète, c'est bien un problème de conversion, pas de représentation.
    Jusqu'à nouvel ordre, je pense que c'est bien un problème de représentation.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Donc conclusion, et pour reprendre le point de départ de la discussion:

    quoiqu'on fasse, la conversion chaine->double (avec atof(), sscanf(), strtod() ...) n'est pas réversible (avec le nombre exact de décimales que l'utilisateur a saisies), et si on veut pouvoir rétablir la chaine à posteriori, il faudrait donc la stocker ?

    Triste réalité...
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  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
    Citation Envoyé par rigobert
    quoiqu'on fasse, la conversion chaine->double (avec atof(), sscanf(), strtod() ...) n'est pas réversible (avec le nombre exact de décimales que l'utilisateur a saisies), et si on veut pouvoir rétablir la chaine à posteriori, il faudrait donc la stocker ?
    Exact.
    Triste réalité...
    As-tu vraiment besoin de nombres à virgules flottantes ?
    Pas de Wi-Fi à la maison : CPL

  18. #18
    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
    Citation Envoyé par rigobert
    quoiqu'on fasse, la conversion chaine->double (avec atof(), sscanf(), strtod() ...) n'est pas réversible
    A partir du moment où plusieurs chaines seront représentées par le même double, je ne vois pas comment faire autrement. double->chaine->double peut facilement être garanti et il existe des algo pour le faire en gardant la chaine la plus courte possible -- mais ce n'est pas accessible avec printf, il faut faire son formatage soi-même. Tu peux éventuellement utiliser un tel algo pour rendre ta chaine. Je n'ai pas de référence sous la main mais http://citeseer.ist.psu.edu/william90how.html devrait être un bon point de départ.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  19. #19
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    Il est possible de faire autrement, mais ce n'est pas super simple, c'est de ne pas passer par des flottants, mais une virgule fixe. Tu gères alors parfaitement le système, mais il te faudra un peu de travail pour faire les conversions (si besoin est...).
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    As-tu vraiment besoin de nombres à virgules flottantes ?
    Oui et non.

    La saisie et les conversions proprement dites se font au sein d'une classe de widget et (presque) toute méthode interne est implémentable, et sa complexité n'est pas forcément un frein. De plus il n'y a pas vraiment de limites fixées pour le nombre de décimales, même si dans la pratique une dizaine devrait amplement suffire. Dans ce contexte, une virgule fixe 64-bit pourrait par ex faire l'affaire.

    Ce qui m'embête plus, c'est au niveau de l'API, de proposer un format de nombre non standard pour les entrées/sorties; demander à l'utilisateur de gérer par ex de la virgule fixe au milieu de calculs scientifiques, de gérer la persistance de ces mêmes nombres, c'est pour le moins ni pratique ni élégant, pour ne pas dire autre chose...

    Citation Envoyé par Jean-Marc.Bourguet
    double->chaine->double peut facilement être garanti et il existe des algo pour le faire en gardant la chaine la plus courte possible -- mais ce n'est pas accessible avec printf, il faut faire son formatage soi-même. Tu peux éventuellement utiliser un tel algo pour rendre ta chaine. Je n'ai pas de référence sous la main mais http://citeseer.ist.psu.edu/william90how.html devrait être un bon point de départ.
    Je vais creuser ça. Merci pour le lien.
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

Discussions similaires

  1. [BigDecimal] Problème d'arrondi
    Par Boosters dans le forum Langage
    Réponses: 4
    Dernier message: 29/08/2006, 09h31
  2. problème d'arrondi à 2 chiffres après virgule
    Par nerick dans le forum Langage
    Réponses: 1
    Dernier message: 05/01/2006, 17h26
  3. Problème d'arrondis
    Par steps5ive dans le forum Access
    Réponses: 5
    Dernier message: 09/12/2005, 17h35
  4. [DECIMAL] problème d'arrondi
    Par Boosters dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 28/11/2005, 15h30
  5. Problème d'arrondi
    Par ptitsoleil87 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 07/01/2005, 09h37

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