Float *10 [Résolu]

Signaler
Messages postés
51
Date d'inscription
vendredi 25 novembre 2005
Statut
Membre
Dernière intervention
19 avril 2008
-
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
-
Bonsoir,
J'ai un soucis avec les floats:

int main()
{
float nb = 3.11;

nb *= 10;
printf("%f", nb);
}

cc main.c && ./a.out
31.099998

comment ce fais-ce?
J'aimerais avoir 31.1 comme resultat...

8 réponses

Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
C'est parce que les float font une approximation des valeurs décimales et certaines ne sont pas représentable exactement en mémoire

En fait le 3.11 et le 31.1 ont une représentation finie en décimal mais en réprésentation binaire c'est pas le cas. Du coup les calculs sont approchés.

Exemple : en décimal, il est impossible de représenté 1/3 avec un nombre fini de chifrres, si on se contente de 4 chiffres :val 1/3> en fait en interne on aura 0.3333val val*3> on aura en interne 0.9999 en non pas 1

Avec des double au lieu de float c'est pareil mais ca se voit moins parce que la précision est meilleurs.
Messages postés
442
Date d'inscription
jeudi 4 avril 2002
Statut
Membre
Dernière intervention
11 août 2008

Essaye

printf("%4f", nb);



et

nb *= 10.0f;

neodelphi
Messages postés
65
Date d'inscription
dimanche 27 juillet 2003
Statut
Membre
Dernière intervention
21 avril 2006

Oui, moi aussi, dans mon projet, je n'ai que des double et j'ai des valeurs qui dérapent vite !

Je crois que le C++ a besoin d'un type qui permettrait de meilleurs résultats.
Messages postés
51
Date d'inscription
vendredi 25 novembre 2005
Statut
Membre
Dernière intervention
19 avril 2008

neodelphi non ca change rien chez moi,
mais je vois le probleme a peu pres, merci ymca2003.
Les doubles ne posent pas de problemes sur cet exemple apparement.

Ce probleme que j'avais etait pour mon recodage du printf %f, quand j'utilise un float, pour recuperer le float, ca marche mais la precision foire, par contre la j'ai essayer de recuper mon float avec un double et ca ne marche plus (il me met 0.0 dans tous les cas), je me sert d'int pour afficher les nombre apres et avant la virgule, peut-etre le cast du double en int bug?
( enfin c'est un autre probleme mais j'aimerais bien finir de maudit printf d: )
Messages postés
65
Date d'inscription
dimanche 27 juillet 2003
Statut
Membre
Dernière intervention
21 avril 2006

Tu peux utiliser l'affichage que tu veux, les nombre stockés en mémoire sont FAUX !

même si tu avais un type doubledoubledouble, il serait toujours impossible de stocker 0.3
Regarde donc comment fonctionne la stockage d'une valeur dans la mantisse et essaie avec 0.3 => impossible.

J'ai déjà essayer d'écrire une lib qui serait un type exact, mais j'ai abandonné, je n'ai pas trouvé de solution évidente.
Messages postés
51
Date d'inscription
vendredi 25 novembre 2005
Statut
Membre
Dernière intervention
19 avril 2008

Oui mais c'etait pour faire un printf qui "aurait l'air" de bien gerer les floats, et puis meme si c'est faux, avec les doubles, tant que ca depasse pas les 6 nbres apres la virgule, ca affiche la bonne chose.
On m'a dit de passer par le binaire, bon, plus tard =)
Messages postés
442
Date d'inscription
jeudi 4 avril 2002
Statut
Membre
Dernière intervention
11 août 2008

Je comprend pas pourquoi il ne pourrait pas stocker 3.11, si le
stockage se fait avec une partie entiere pour les nombres et une autre
pour la virgule, trois chiffre ça devrait passer nan ?

neodelphi
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
En décimal oui, en binaire non.

0.11 ne peut pas s'exprimer en puissance de 2
0.11 : 1/16 + 1/32 + 1/64 + 1/2048 + 1/8192 + 1/131072 = 0,10999298095703125

Donc on tombe pas sur 0.11 pile poil.