plate-forme de compilation prenant mode d'arrondi FPU en compte dans l'impression, les conversions
-
25-09-2019 - |
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:
- 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?
- est l'un des comportements standard?
- 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
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.