bonjour tout le monde,
une question de vrai débutant :
Avec le programme essai.c suivant
int main(void) {
return ((1.7 + 0.1) == 1.8) ? 1 : 0;
return ((x + 0.1) == 1.8) ? 1 : 0;
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
bonjour tout le monde,
une question de vrai débutant :
Avec le programme essai.c suivant
int main(void) {
return ((1.7 + 0.1) == 1.8) ? 1 : 0;
return ((x + 0.1) == 1.8) ? 1 : 0;
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
bonjour tout le monde,
une question de vrai débutant :
Avec le programme essai.c suivant
int main(void) {
return ((1.7 + 0.1) == 1.8) ? 1 : 0;
return ((x + 0.1) == 1.8) ? 1 : 0;
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
int main(void) {
float x;
x = 1.7;
return ((x + 0.1) == 1.8) ? 1 : 0;
}
j'obtiens :
$ gcc -Wall -o essai essai.c; ./essai; echo $?
0
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
int main(void) {
float x;
x = 1.7;
return ((x + 0.1) == 1.8) ? 1 : 0;
}
j'obtiens :
$ gcc -Wall -o essai essai.c; ./essai; echo $?
0
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
int main(void) {
float x;
x = 1.7;
return ((x + 0.1) == 1.8) ? 1 : 0;
}
j'obtiens :
$ gcc -Wall -o essai essai.c; ./essai; echo $?
0
Pourtant, le programme
#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
}
affiche :
1.800000 et 1.800000
float x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
affiche :
1.800000 et 1.800000
Apparremment, 1.7+0.1 et x+0.1 sont égaux ;
j'imagine qu'il s'agit d'un problème de représentation des flottants
(et une explication, si possible).
float x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
affiche :
1.800000 et 1.800000
Apparremment, 1.7+0.1 et x+0.1 sont égaux ;
j'imagine qu'il s'agit d'un problème de représentation des flottants
(et une explication, si possible).
float x = 1.7;
printf("%f et %fn", 1.7 + 0.1, x + 0.1);
affiche :
1.800000 et 1.800000
Apparremment, 1.7+0.1 et x+0.1 sont égaux ;
j'imagine qu'il s'agit d'un problème de représentation des flottants
(et une explication, si possible).
L'usage des doubles/float n'est pas simple si on doit se préoccupper des
erreurs. Aussi il est souvent recommandé de ne pas utiliser d'égalité
stricte, mais d'introduire une tolérance: a==b devenant fabs(a-b)<=seuil.
L'usage des doubles/float n'est pas simple si on doit se préoccupper des
erreurs. Aussi il est souvent recommandé de ne pas utiliser d'égalité
stricte, mais d'introduire une tolérance: a==b devenant fabs(a-b)<=seuil.
L'usage des doubles/float n'est pas simple si on doit se préoccupper des
erreurs. Aussi il est souvent recommandé de ne pas utiliser d'égalité
stricte, mais d'introduire une tolérance: a==b devenant fabs(a-b)<=seuil.
Emmanuel a écrit :
> int main(void) {
> float x;
> x = 1.7;
> return ((x + 0.1) == 1.8) ? 1 : 0;
> }
>
> j'obtiens :
>
> $ gcc -Wall -o essai essai.c; ./essai; echo $?
> 0
Attention, le 1.7 de x est un float ici (23bits de précision), et le 0.1
(et le 1.8) de l'addition (ou de la comparaison) est un double (52bits
de précision).
Bref l'un a des bits significatifs en trop par rapport à l'autre. Le
test ne veut rien dire.
C'est l'erreur classique que l'on trouve dans les exos de physiques
quand les élèves sortent un résultat avec 5 chiffres significatifs
alors que les données du problème n'en ont que 2.. les chiffres en
trop n'ont pas de sens.
Par ailleurs dans ton 1er test avec des constantes, tout est double, le
test a déjà plus de sens, mais il est probable que l'optimiseur minimal
remplace 1.7 + 0.1 par 1.8 directement, d'où égalité stricte bit à bits
(sans compter que si c'est stocké dans des registres, il y a des bits
supplémentaires par rapport au formats IEEE double).
En outre il faut savoir que le décimal 0.1 ne se représente pas
*exactement* en binaire.
Ce problème se produit avec tout nombre décimal qui n'est pas une
puissance de deux.
Aussi, il vaut mieux privilégier les puissances de deux dans ses
constantes.. quitte à renormaliser le calcul via une seule
division/multiplication tout à la fin de l'algo si c'est possible.
> Pourtant, le programme
>
> #include <stdio.h>
> int main(void) {
> float x;
> x = 1.7;
> printf("%f et %fn", 1.7 + 0.1, x + 0.1);
> }
>
> affiche :
> 1.800000 et 1.800000
Ca ne veut rien dire.. Le printf effectue une conversion des float en
double et un arrondi pour l'affichage.
Bref, affiche plutot les nombres en binaires/hexa si tu veux voir si
quelque chose diffère au niveau des bits:
union {long int i[2]; double d;} nb;
nb.d = 1.7 + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
nb.d = x + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
Emmanuel a écrit :
> int main(void) {
> float x;
> x = 1.7;
> return ((x + 0.1) == 1.8) ? 1 : 0;
> }
>
> j'obtiens :
>
> $ gcc -Wall -o essai essai.c; ./essai; echo $?
> 0
Attention, le 1.7 de x est un float ici (23bits de précision), et le 0.1
(et le 1.8) de l'addition (ou de la comparaison) est un double (52bits
de précision).
Bref l'un a des bits significatifs en trop par rapport à l'autre. Le
test ne veut rien dire.
C'est l'erreur classique que l'on trouve dans les exos de physiques
quand les élèves sortent un résultat avec 5 chiffres significatifs
alors que les données du problème n'en ont que 2.. les chiffres en
trop n'ont pas de sens.
Par ailleurs dans ton 1er test avec des constantes, tout est double, le
test a déjà plus de sens, mais il est probable que l'optimiseur minimal
remplace 1.7 + 0.1 par 1.8 directement, d'où égalité stricte bit à bits
(sans compter que si c'est stocké dans des registres, il y a des bits
supplémentaires par rapport au formats IEEE double).
En outre il faut savoir que le décimal 0.1 ne se représente pas
*exactement* en binaire.
Ce problème se produit avec tout nombre décimal qui n'est pas une
puissance de deux.
Aussi, il vaut mieux privilégier les puissances de deux dans ses
constantes.. quitte à renormaliser le calcul via une seule
division/multiplication tout à la fin de l'algo si c'est possible.
> Pourtant, le programme
>
> #include <stdio.h>
> int main(void) {
> float x;
> x = 1.7;
> printf("%f et %fn", 1.7 + 0.1, x + 0.1);
> }
>
> affiche :
> 1.800000 et 1.800000
Ca ne veut rien dire.. Le printf effectue une conversion des float en
double et un arrondi pour l'affichage.
Bref, affiche plutot les nombres en binaires/hexa si tu veux voir si
quelque chose diffère au niveau des bits:
union {long int i[2]; double d;} nb;
nb.d = 1.7 + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
nb.d = x + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
Emmanuel a écrit :
> int main(void) {
> float x;
> x = 1.7;
> return ((x + 0.1) == 1.8) ? 1 : 0;
> }
>
> j'obtiens :
>
> $ gcc -Wall -o essai essai.c; ./essai; echo $?
> 0
Attention, le 1.7 de x est un float ici (23bits de précision), et le 0.1
(et le 1.8) de l'addition (ou de la comparaison) est un double (52bits
de précision).
Bref l'un a des bits significatifs en trop par rapport à l'autre. Le
test ne veut rien dire.
C'est l'erreur classique que l'on trouve dans les exos de physiques
quand les élèves sortent un résultat avec 5 chiffres significatifs
alors que les données du problème n'en ont que 2.. les chiffres en
trop n'ont pas de sens.
Par ailleurs dans ton 1er test avec des constantes, tout est double, le
test a déjà plus de sens, mais il est probable que l'optimiseur minimal
remplace 1.7 + 0.1 par 1.8 directement, d'où égalité stricte bit à bits
(sans compter que si c'est stocké dans des registres, il y a des bits
supplémentaires par rapport au formats IEEE double).
En outre il faut savoir que le décimal 0.1 ne se représente pas
*exactement* en binaire.
Ce problème se produit avec tout nombre décimal qui n'est pas une
puissance de deux.
Aussi, il vaut mieux privilégier les puissances de deux dans ses
constantes.. quitte à renormaliser le calcul via une seule
division/multiplication tout à la fin de l'algo si c'est possible.
> Pourtant, le programme
>
> #include <stdio.h>
> int main(void) {
> float x;
> x = 1.7;
> printf("%f et %fn", 1.7 + 0.1, x + 0.1);
> }
>
> affiche :
> 1.800000 et 1.800000
Ca ne veut rien dire.. Le printf effectue une conversion des float en
double et un arrondi pour l'affichage.
Bref, affiche plutot les nombres en binaires/hexa si tu veux voir si
quelque chose diffère au niveau des bits:
union {long int i[2]; double d;} nb;
nb.d = 1.7 + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
nb.d = x + 0.1;
printf("%08x%08xn", nb.i[0], nb.i[1]);
A ce propos, les standard de codages industriels tel Misra-c
(http://www.misra.org.uk/) interdisent l'utilisation de "==" et "!=" sur
les floats.
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
A ce propos, les standard de codages industriels tel Misra-c
(http://www.misra.org.uk/) interdisent l'utilisation de "==" et "!=" sur
les floats.
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
A ce propos, les standard de codages industriels tel Misra-c
(http://www.misra.org.uk/) interdisent l'utilisation de "==" et "!=" sur
les floats.
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
Il y a des cas où le test d'égalité a un sens. Mais bon...
Faut bien se dire que de tels "standards de codages industriels"
ont leur spécificité. À la même URL:
/* Rule 13: Advisory */
/* The basic types char, short, int, long, float and double should not */
/* be used. */
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
Il y a des cas où le test d'égalité a un sens. Mais bon...
Faut bien se dire que de tels "standards de codages industriels"
ont leur spécificité. À la même URL:
/* Rule 13: Advisory */
/* The basic types char, short, int, long, float and double should not */
/* be used. */
http://www.abxsoft.com/misra/misra-test.html
/* Rule 50: Required */
/* Floating point variables shall not be tested for exact equality or */
/* inequality. */
MISRA-C [1998:2004] Function Definition: rule50
Il y a des cas où le test d'égalité a un sens. Mais bon...
Faut bien se dire que de tels "standards de codages industriels"
ont leur spécificité. À la même URL:
/* Rule 13: Advisory */
/* The basic types char, short, int, long, float and double should not */
/* be used. */
Non. Pas de problème avec 8.5, qui n'est pas une puissance de 2. :)
Beurk. Utiliser %a (ISO C99).
Non. Pas de problème avec 8.5, qui n'est pas une puissance de 2. :)
Beurk. Utiliser %a (ISO C99).
Non. Pas de problème avec 8.5, qui n'est pas une puissance de 2. :)
Beurk. Utiliser %a (ISO C99).
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
> Beurk. Utiliser %a (ISO C99).
Ah? oui peut-être.. mais c'est un détail superflu pour le sujet à mon
avis. D'ailleurs moi je voulais imprimer des *entiers* et pas des
flottants en hexa, donc %a est hors sujet.
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
> Beurk. Utiliser %a (ISO C99).
Ah? oui peut-être.. mais c'est un détail superflu pour le sujet à mon
avis. D'ailleurs moi je voulais imprimer des *entiers* et pas des
flottants en hexa, donc %a est hors sujet.
Cela dit suivant le parseur utilisé on peut avoir des soucis car la
partie "0.5" peut être traduite par un 5*0.1, avec le 0.1 qui n'est pas
exact.
> Beurk. Utiliser %a (ISO C99).
Ah? oui peut-être.. mais c'est un détail superflu pour le sujet à mon
avis. D'ailleurs moi je voulais imprimer des *entiers* et pas des
flottants en hexa, donc %a est hors sujet.