45 votes

Précision de la multiplication par 1,0 et conversion d'int en float

Peut-on supposer que la condition (int)(i * 1.0f) == i est vrai pour tout nombre entier i ?

71voto

Stephen Canon Points 58003

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.

15voto

thkala Points 36148

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 être true si le compilateur optimise la conversion en float et retour.

-5voto

Mohit Sehgal Points 432

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X