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.
Forum Programmation.c atof : arrondi etrange
PostĂ© par Enzo Bricolo đ âđ .
Ătiquettes :
aucune
3
sept.
2004
# Pas mal.
PostĂ© par reno . ĂvaluĂ© Ă 2.
Ah, le calcul flottant, c'est une source inepuisable d'"amusements"..
# C'est comme tout...
PostĂ© par pasBill pasGates . ĂvaluĂ© Ă 2.
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 mac . ĂvaluĂ© Ă 2.
# heu...
PostĂ© par bergamote23 . ĂvaluĂ© Ă 2.
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 Enzo Bricolo đ âđ . ĂvaluĂ© Ă 2.
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 Enzo Bricolo đ âđ . ĂvaluĂ© Ă 1.
#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 Olivier MARTIN . ĂvaluĂ© Ă 1.
[^] # Re: C'est un concours cest ca?
PostĂ© par ceituna . ĂvaluĂ© Ă 3.
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... :=/
[^] # Re: C'est un concours cest ca?
PostĂ© par Enzo Bricolo đ âđ . ĂvaluĂ© Ă 1.
Enzo Bricolo
[^] # Re: C'est un concours cest ca?
PostĂ© par ceituna . ĂvaluĂ© Ă 1.
75,33 est "converti" en 75,33000183105469 sur un codage 32 bits...
Donc, le "cast" te donne 7533... CQFD.
PS : pour ceux qui veulent tester des valeurs, j'ai trouvé ce lien entre-temps... :
http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html(...)
et
http://www.h-schmidt.net/FloatApplet/IEEE754.html(...)
[^] # Re: C'est un concours cest ca?
PostĂ© par Enzo Bricolo đ âđ . ĂvaluĂ© Ă 1.
Dans ma recette, la multiplication par 100.0 distribuait les erreurs d'arrondi sur certaines valeurs trÚs peu fréquentes, d'ou l'impression de "bug".
Moralité, évitez l'emploi de flottant dans le calcul de montant ou pensez à arrondi les valeurs au centimes prÚs avant affichage.
Enzo Bricolo
PS : J'ai fouillé l'ensemble des sources manipulées par le presta et j'ai retrouvé 3 fois le "cast" malencontreux ... rogntudju ...
Suivre le flux des commentaires
Note : les commentaires appartiennent Ă celles et ceux qui les ont postĂ©s. Nous nâen sommes pas responsables.