7
votes

Conversion de type implicite en c

Je suis tombé sur l'exemple suivant sur Wikipedia ( http://fr.wikipedia.org/wiki / Type_conversion # implicit_type_conversion ). XXX

Leur explication: "Ce comportement impair est causé par une coute implicite d'i_value à flotter lorsqu'elle est comparée à F_Value; un casting qui perd une précision , rendre les valeurs comparées différentes. "

n'est-ce pas faux? Si i_Value était lancé pour flotter, les deux auraient la même perte de précision et ils seraient égaux. Donc i_value doit être coulé au double.


4 commentaires

Avec g ++ (GCC 4.6.2), j'obtiens 1 pour l'égalité.


@Kerrek: Et moi. Dans vs, je reçois 0.


@Olicharlesworth: Je suis curieux de changer le littéral sur f ou du type à double - i get 1 dans tous les cas ...


Vous utilisez probablement un système X64 qui n'utilise pas 10 octets étendus, mais plutôt doubles habituels. Vous pouvez également l'observer sur CPU 32 bits avec -MFPMath = SSE -MSSE.


3 Réponses :


-1
votes

Je crois que la plus grande valeur entière d'un point flottant IEEE 32 bits peut contenir est 1048576, ce qui est inférieur au nombre ci-dessus. Donc, il est définitivement vrai que la valeur ponctuelle flottante ne tiendra pas exactement 16777217.

La pièce, je ne suis pas sûr de savoir comment le compilateur fait la comparaison entre deux types de nombres différents (c'est-à-dire un flotteur et un int). Je peux penser à trois manières différentes que cela pourrait être fait:

1) Convertissez les deux valeurs en "float" (cela doit apporter les valeurs identiques, ce n'est probablement pas ce que le compilateur fait)

2) Convertissez les deux valeurs en "INT" (ceci peut ou ne peut pas leur montrer la même chose ... la conversion à un intors tronque souvent, de sorte que la valeur du point flottant est 16777216.99999, puis la conversion de "INT" tronquerait )

3) Convertissez les deux valeurs en «Double». Je suppose que c'est ce que le compilateur ferait. Si c'est ce que fait le compilateur, les deux valeurs seraient définitivement différentes. Un double peut tenir 16777217 exactement, et cela pourrait également représenter exactement la valeur du point flottant que 16777217.0 se convertit (ce qui n'est pas exactement 16777217.0).


0 commentaires

7
votes

Non, dans le cas de l'exploitant d'égalité, les "conversions arithmétiques habituelles" se produisent, qui commencent:

  • Tout d'abord, si le type réel correspondant d'un seul opérande est double , l'autre opérande est converti, sans changement de type Domaine, à un type dont le type réel correspondant est Long Double .
  • Sinon, si le type réel correspondant d'un seul opérand est double , l'autre opérande est converti, sans changement de type domaine, à un type dont le type réel correspondant est double .
  • Sinon, si le type réel correspondant d'un seul opérand est float , l'autre opérande est converti, sans changement de type domaine, à un type dont le type réel correspondant est float .

    Ce dernier cas s'applique ici: i_value est converti en float .

    La raison pour laquelle vous pouvez voir un résultat étrange de la comparaison, malgré cela, c'est à cause de cette mise en garde aux conversions arithmétiques habituelles:

    Les valeurs des opérandes flottantes et des résultats de flottants Les expressions peuvent être représentées en plus de précision et de gamme que cela requis par le type; Les types ne sont pas modifiés ainsi.

    C'est ce qui se passe: le type du type converti i_value est toujours float , mais dans cette expression, votre compilateur profite de cette latitude et de la représentation plus grande précision que float . Il s'agit de comportement typique du compilateur lors de la compilation du point flottant compatible 387, car le compilateur laisse des valeurs temporaires sur la pile à point flottant, qui stocke des nombres de points flottants dans un format de précision étendu 80 bits.

    Si votre compilateur est GCC , vous pouvez désactiver cette précision supplémentaire en donnant à l'option -ffloat-store ligne de commande.


2 commentaires

Sur X64 GCC utilise une instruction CVTSI2SSL explicite qui convertit entier pour flotter. Sur le X86, cependant, c'est ce qui se passe exactement et qu'une plus grande précision est en fait encore supérieure à la double.


@ KONRAD.KRUCZYNSKI: Oui, et vous pouvez obtenir le même résultat sur x86 en fournissant l'option -mfpmath = sse (qui nécessite également un -MSse ou une option qui implique cette).



0
votes

Il y a de bonnes réponses ici. Vous devez faire très attention à la conversion entre divers entiers et diverses représentations de points flottants.

Je ne teste généralement pas les numéros de points flottants pour l'égalité, en particulier si l'un d'entre eux provient d'un couplage implicite ou explicite d'un type entier. Je travaille sur une application remplie de calculs géométriques. Autant que possible, nous travaillons avec des entiers normalisés (en forçant une précision maximale que nous accepterons dans les données d'entrée). Pour les cas où vous devez utiliser un point flottant, nous appliquerons une valeur absolue à la différence si la comparaison est nécessaire.


0 commentaires