Forum Programmation.c atof : arrondi etrange

Posté par  .
Étiquettes : aucune
-1
3
sept.
2004
Je viens de porter un vieux bout de code fait par un prestataire sur une SUN vers un PC sous w2k.

En recettant, j'ai obtenu une erreur d'arrondi étrange dans une fonction qui convertissait un montant stocké dans un chaine dans un entier(montant en centimes).

Outre le fait que la fonction etait "grouik", je ne comprenais pas
l'erreur. Je l'ai reproduite avec çà :

char montant[16];
strcpy(montant, "75.32");
i=(int )(atof(montant)*100.0);

i vaut 7531 Ă  la fin. J'ai mis du temps Ă  percuter. Et vous ?

Enzo

PS : Dommage, le prestataire qui m'a laissé çà est dèjà parti. Je lui aurai fait payer l'apéro.
  • # Pas mal.

    Posté par  . Évalué à 2.

    Cela m'a pris aussi, un certain temps..

    Ah, le calcul flottant, c'est une source inepuisable d'"amusements"..
  • # C'est comme tout...

    Posté par  . Évalué à 2.

    Ben comme tout probleme informatique, une fois qu'on t'a explique comment ca marche(comment un float est stocke dans ce cas ci), tu trouves ca hyper logique, alors que pendant les 2-3 jours precedents tu t'es tire les cheveux en te demandant si les extra-terrestres jouaient avec ta machine.

    C'est ca le cote marrant de l'informatique, expliquer a tes collegues sur quelle connerie triviale tu as perdu 2 jours :+)
  • # Et l'homme inventa le BCD...

    Posté par  . Évalué à 2.

  • # heu...

    Posté par  . Évalué à 2.

    C'est ben gentil, mais il y aurait pas quelqu'un pour expliquer de manière simple ce qui
    ce passe Ă  ceux qui n'ont pas le niveau pour comprendre d'eux mĂŞme mais qui sont tout de mĂŞme intriguer par le truc ?

    Faites pas semblant, vous attendiez tous une question de ce genre pour pouvoir flatter votre Ă©go..
    • [^] # Re: heu...

      Posté par  . Évalué à 2.

      Je pensais avoir compris mais je ne comprends pas tout.

      http://www.greatsnakes.com/Sepal/d5/d8/atof_8c.html(...)

      atof appelle strtod

      http://www.greatsnakes.com/Sepal/d2/d4/strtod_8c.html#a0(...)

      Mais çà devrait marcher.


      Je vais regarder si çà ne dépend pas de l'implémentation.

      Apparement je sui spas le seul a me poser des questions.

      http://mail-index.netbsd.org/port-mips/1999/02/06/0000.html(...)

      A plus,

      Enzo Bricolo
      • [^] # Re: heu...

        Posté par  . Évalué à 1.

        En fait, c'est lié au processeur (un Pentium III ici).


        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>

        void main (){
        char montant[16];

        strcpy(montant, "75.32");
        fprintf(stderr, "(%s) -> (%e) -> (%d)\n",
        montant,atof(montant)*100.0, (int )(atof(montant)*100.0));

        exit(0);
        }

        $./test_atof
        (75.32) -> (7.532000e+003) -> (7531)


        Voir ce thread entre autre.

        http://gcc.gnu.org/ml/gcc-bugs/1998-09/msg00584.html(...)

        Enzo Bricolo
        • [^] # C'est un concours cest ca?

          Posté par  . Évalué à 1.

          Vous pouvez pas expliquer CLAIREMENT le pourquoi du problème plutot que renvoyez sur un topic obscur?
          • [^] # Re: C'est un concours cest ca?

            Posté par  (site web personnel) . Évalué à 3.

            Use the force, Luke... (c)


            Commençons par le début...

            Un flottant, est défini (sur 32 bits) par :
            1 bit de signe
            8 bits pour l'exposant (codé en complément à 2)
            le reste (23 bits) pour la mantisse... (comprise entre 1 et 2)


            Ainsi, le nombre 8 s'Ă©crit 1.0 *2^3, soit :
            (signe) + (exposant) + (mantisse)
            0 + (3) + (0.0000)

            soit, en binaire :
            0 . 10000010 . 00000000000000000000000


            Tu suis toujours ?

            On prend un nombre plus difficile :
            9 soit : 1,125 *2^3, soit :
            (signe) + (exposant) + (mantisse)
            0 + (3) + (0.1250)

            soit, en binaire :
            0 . 10000010 . 00100000000000000000000



            Maintenant, on prend l'exemple cité :
            75,32 soit 1,176875 *2^6, soit :
            (signe) + (exposant) + (mantisse)
            0 + (6) + (0,176875)
            en binaire :
            0 . 10000101 . 00101101010001111010111


            Or, cela représente une valeur de
            75, 31999969482422 (+ un petit quelque chose).


            Le pb du programme vient du Forcage de type (cast pour les puristes), qui tronque la valeur 7531,999969482422 en 7531.

            Une belle programmation aurait plutĂ´t fait un arrondi avant de forcer au type (int).

            Morale : Des fois, un arrondi est plus préci qu'un calcul "exact" (message perso pour les fanas de la qualité max et de la précision max).

            CQFD.

            PS : merci de me corriger si j'ai dit une bétise... C'est fréquent quand il fait beau... :=/

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.