Peut-on supposer que la condition (int)(i * 1.0f) == i
est vrai pour tout nombre entier i
?
Réponses
Trop de publicités?No.
Si i
est suffisamment grande pour que int(float(i)) != i
(en supposant que le flottant est une précision simple IEEE-754, i = 0x1000001
suffit pour le démontrer), alors c'est faux, car la multiplication par 1.0f
force une conversion en float
qui change la valeur même si la multiplication suivante ne le fait pas.
Toutefois, si i
est un entier de 32 bits et double
est un double IEEE-754, alors il est es vrai que int(i*1.0) == i
.
Pour être tout à fait clair, la multiplication par 1.0f
es exact. C'est la conversion de int
a float
qui ne l'est peut-être pas.
Non, IEEE-754 Les nombres à virgule flottante ont une plus grande plage dynamique que les nombres entiers, au prix de la précision des nombres entiers pour la même largeur de bit.
Voyez par exemple le résultat de ce petit extrait :
int main() {
int x = 43046721;
float y = x;
printf("%d\n", x);
printf("%f\n", y);
}
43046721
ne peut pas être représenté correctement dans les 24 bits de précision disponibles dans un système de 32 bits. float
Le résultat est donc quelque chose de ce genre :
43046721
43046720.000000
En fait, je m'attendrais à ce que tout nombre impair supérieur à 16 777 216 ait le même problème lors de la conversion en 32 bits. float
numéro.
Quelques points d'intérêt :
-
Cela a plus à voir avec la conversion implicite int-float qu'avec la multiplication elle-même.
-
Ce problème n'est en aucun cas propre au C. Par exemple, Java est également sujet au même problème.
-
La plupart des compilateurs ont des options d'optimisation qui peuvent affecter la façon dont ces conversions sont traitées, en ignorant certaines restrictions de la norme. Dans un tel cas,
(int)((float)x * 1.0f) == x
pourrait toujours êtretrue
si le compilateur optimise la conversion enfloat
et retour.
Non, c'est absolument faux pour tous les entiers à cause de la distribution de type. Vérifiez le code.
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 2147483647; ++i) {
if ((int)(i * 1.0f) != i) {
printf("not equal\n");
break;
}
}
printf("out of the loop\n");
getchar();
return 0;
}
Ce code suppose que vous prenez des entiers de 32 bits.