plate-forme de compilation prenant mode d'arrondi FPU en compte dans l'impression, les conversions

StackOverflow https://stackoverflow.com/questions/2595563

Question

EDIT: Je l'avais fait une erreur lors de la session de débogage qui me conduit à poser cette question. Les différences que je voyais étaient en fait dans l'impression d'un double et un double en analyse syntaxique (strtod). La réponse de Stephen couvre encore ma question très bien même après cette rectification, donc je pense que je vais laisser seul la question dans le cas où il est utile à quelqu'un.

Certains (la plupart) des plates-formes de compilation C J'ai accès à ne prenez pas le mode d'arrondi FPU en compte lorsque

  • la conversion d'un entier de 64 bits à double;
  • l'impression d'un double.

Rien de très exotique ici. Mac OS X Leopard, divers systèmes Linux récents et les variantes BSD, Windows

D'autre part, Mac OS X Snow Leopard semble prendre le mode d'arrondi en compte lorsque vous faites ces deux choses. Bien sûr, avoir des comportements différents me contrarie pas de fin.

Voici les extraits typiques pour les deux cas:

#if defined(__OpenBSD__) || defined(__NetBSD__) 
# include <ieeefp.h>
# define FE_UPWARD FP_RP
# define fesetround(RM) fpsetround(RM)
#else 
# include <fenv.h>
#endif

#include <float.h>
#include <math.h>

fesetround(FE_UPWARD);

...
double f;
long long b = 2000000001;
b = b*b;
f = b;

...
printf("%f\n", 0.1);

Mes questions sont les suivantes:

  1. I Y at-il quelque chose de non-laid qui peut faire pour normaliser le comportement sur toutes les plateformes? Certains paramètre caché pour dire les plates-formes qui prennent en compte le mode d'arrondi pas ou vice-versa?
  2. est l'un des comportements standard?
  3. Qu'est-ce que je risque de rencontrer lorsque le mode d'arrondi FPU n'est pas utilisé? Round vers zéro? Arrondi au plus proche? S'il vous plaît, dites-moi qu'il n'y a qu'une seule alternative:)

En ce qui concerne 2. J'ai trouvé l'endroit dans la norme où il est dit que les flotteurs convertis en entiers sont toujours tronqués (arrondi vers zéro) mais je ne pouvais pas trouver quoi que ce soit pour l'entier -.> Direction flotteur

Était-ce utile?

La solution

Si vous avez pas encore défini le mode d'arrondi, il devrait être le mode par défaut IEEE-754, ce qui est. Tour à la plus proche

Pour les conversions de nombre entier à flotter, la norme C dit (§6.3.1.4):

  

Si une valeur de type entier est   converti en un vrai type flottant, si   la valeur en cours de conversion peut être   représenté exactement dans le nouveau type,   il est inchangé. Si la valeur étant   converti est dans la plage de valeurs   qui peuvent être représentés, mais ne peut pas être   représenté exactement, le résultat est   soit le plus proche ou plus proche   faible valeur représentable, choisi dans   une manière de mise en œuvre définie. Si   la valeur en cours de conversion est en dehors   la plage de valeurs qui peuvent être   représenté, le comportement est   non défini.

Ainsi, les deux comportements sont conformes à la norme C.

La norme C dit (§F.5) que les conversions entre les formats à virgule flottante IEC60559 et des séquences de caractères arrondies correctement selon la norme IEEE-754. Pour les formats non-IEC60559, ce qui est recommandé, mais pas obligatoire. En 1985, la norme IEEE-754 dit (article 5.4):

  

Les conversions sont arrondies correctement   comme indiqué dans la section 4 pour opérandes   se situant dans les plages spécifiées dans   Tableau 3. Dans le cas contraire, pour arrondir à   le plus proche, l'erreur dans le converti   résultat ne doit pas dépasser de plus de   0,47 unités chiffre le moins significatif de la destination est l'erreur   encourue par l'arrondissement   cahier des charges de l'article 4, à condition   que l'exposant sur / underflow ne   se produire. Dans les modes d'arrondi orienté   l'erreur a le signe correct   et ne doit pas dépasser 1,47 unités dans le   dernière place.

Qu'est-ce que la section (4) dit en fait est que l'opération doit avoir lieu selon le mode d'arrondi en vigueur. C'est à dire. si vous changez le mode d'arrondi, IEEE-754 indique que le résultat de la conversion de chaîne en fonction du flottant> devrait changer en conséquence. Même chose pour integer-> conversions de flotteur.

La révision 2008 de la norme IEEE-754 dit (article 4.3):

  

L'attribut arrondi direction   affecte toutes les opérations de calcul   qui pourrait être inexacte. numérique inexact   résultats à virgule flottante ont toujours   même signe que le résultat non arrondi.

Les deux conversions sont définies comme des opérations de calcul à l'article 5, à nouveau, ils doivent être effectués selon le mode d'arrondi en vigueur.

Je dirais que Snow Leopard a ici le comportement correct (en supposant qu'il est correctement arrondir les résultats selon le mode d'arrondi en vigueur). Si vous voulez forcer l'ancien comportement, vous pouvez toujours envelopper vos appels printf dans le code qui change le mode d'arrondi, je suppose, bien que ce soit évidemment pas idéal.

Vous pouvez utiliser le spécificateur de format %a (virgule flottante hexadécimal) sur les plates-formes conformes C99. Étant donné que le résultat de cette conversion est toujours exacte, il ne sera jamais effectuée par le mode d'arrondi en vigueur. Je ne pense pas que la bibliothèque de Windows C prend en charge %a, mais vous pouvez probablement le port de la mise en œuvre de BSD ou glibc assez facilement si vous en avez besoin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top