Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

INFITINY et double

10 réponses
Avatar
JKB
Bonjour à tous,

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ? Je pensais bêtement faire :

double x;
x = (double) INFINITY;

Ça fonctionne avec gcc et d'autres compilos C, mais le DEC C renacle
et renvoie une valeur absconse. D'où la question : est-ce que le fait
de caster INFINITY en double est portable ou non ?

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr

10 réponses

Avatar
Marc
JKB wrote:

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



HUGE_VAL ?

(je ne connais pas avec certitude la réponse à l'autre question)
Avatar
JKB
Le Sat, 30 Jul 2011 15:24:23 +0000 (UTC),
Marc écrivait :
JKB wrote:

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



HUGE_VAL ?

(je ne connais pas avec certitude la réponse à l'autre question)



Non, je ne crois pas. Dans ma doc, il est marqué que HUGE_VAL peut
renvoyer autre chose que inf, par exemple la valeur maximale représentable
pour un certain type...

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Marc
JKB wrote:

Le Sat, 30 Jul 2011 15:24:23 +0000 (UTC),
Marc écrivait :
JKB wrote:

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



HUGE_VAL ?

(je ne connais pas avec certitude la réponse à l'autre question)



Non, je ne crois pas. Dans ma doc, il est marqué que HUGE_VAL peut
renvoyer autre chose que inf, par exemple la valeur maximale représentable
pour un certain type...



Il me semble que l'intention est que HUGE_VAL soit l'infini s'il existe et
autre chose (DBL_MAX ?) sinon. Mais je reconnais que la doc n'inspire pas
confiance.

J'espère que quelqu'un d'autre passera dans le coin avec une meilleure réponse :-/
Avatar
Alexandre Bacquart
On 07/31/2011 12:22 AM, Marc wrote:
JKB wrote:

Le Sat, 30 Jul 2011 15:24:23 +0000 (UTC),
Marc écrivait :
JKB wrote:

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



HUGE_VAL ?

(je ne connais pas avec certitude la réponse à l'autre question)



Non, je ne crois pas. Dans ma doc, il est marqué que HUGE_VAL peut
renvoyer autre chose que inf, par exemple la valeur maximale représentable
pour un certain type...



Il me semble que l'intention est que HUGE_VAL soit l'infini s'il existe et
autre chose (DBL_MAX ?) sinon. Mais je reconnais que la doc n'inspire pas
confiance.

J'espère que quelqu'un d'autre passera dans le coin avec une meilleure réponse :-/



Toutes les FPU ne peuvent pas représenter l'infini, que ce soit pour
float ou double. Ainsi, même en ayant recours à l'assembleur, on est pas
sûr de pouvoir l'obtenir. La norme ne peut donc rien garantir (gageons
que dans la majorité des cas, cela fonctionne).

Avant C89, il y avait bien atof("infinity"), mais c'est, au mieux, aussi
peu fiable que HUGE_VAL. Ca n'a au final que le mérite d'être plus clair
sur l'intention du programmeur. En bref, pas de solution portable à 100%.

En fait, même INFINITY ne garantit pas que la valeur est la
représentation de l'infini pour un float :

================================================================== The macro INFINITY expands to a constant expression of type float
representing positive or unsigned infinity, if available; else to a
positive constant of type float that overflows at translation time.

In this case, using INFINITY will violate the constraint in 6.4.4 and
thus require a diagnostic.
==================================================================
HUGE_VAL semble hélas être le meilleur compromis.

On peut cependant déterminer si l'infini est représentable avec :

#ifndef FP_INFINITE
// pas d'infini
#endif

D'après le rationale :

================================================================== What is INFINITY on machines that do not support infinity? It should be
defined along the lines of: #define INFINITY 9e99999f, where there are
enough 9s in the exponent so that the value is too large to represent as
a float, hence, violates the constraint of 6.4.4 Constants.

In addition, the number classification macro FP_INFINITE should not be
defined. That allows an application to test for the existance of
FP_INFINITE as a safe way to determine if infinity is supported; this is
the feature test macro for support for infinity.
==================================================================
<HS>
En C++, même combat, en plus expressif grâce à :
numeric_limits<float>::has_infinity.
et
numeric_limits<double>::has_infinity.
</HS>


--
Alexandre
Avatar
JKB
Le Sun, 31 Jul 2011 03:01:19 +0200,
Alexandre Bacquart écrivait :
On 07/31/2011 12:22 AM, Marc wrote:
JKB wrote:

Le Sat, 30 Jul 2011 15:24:23 +0000 (UTC),
Marc écrivait :
JKB wrote:

Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



HUGE_VAL ?

(je ne connais pas avec certitude la réponse à l'autre question)



Non, je ne crois pas. Dans ma doc, il est marqué que HUGE_VAL peut
renvoyer autre chose que inf, par exemple la valeur maximale représentable
pour un certain type...



Il me semble que l'intention est que HUGE_VAL soit l'infini s'il existe et
autre chose (DBL_MAX ?) sinon. Mais je reconnais que la doc n'inspire pas
confiance.

J'espère que quelqu'un d'autre passera dans le coin avec une meilleure réponse :-/



Toutes les FPU ne peuvent pas représenter l'infini, que ce soit pour
float ou double. Ainsi, même en ayant recours à l'assembleur, on est pas
sûr de pouvoir l'obtenir. La norme ne peut donc rien garantir (gageons
que dans la majorité des cas, cela fonctionne).

Avant C89, il y avait bien atof("infinity"), mais c'est, au mieux, aussi
peu fiable que HUGE_VAL. Ca n'a au final que le mérite d'être plus clair
sur l'intention du programmeur. En bref, pas de solution portable à 100%.

En fait, même INFINITY ne garantit pas que la valeur est la
représentation de l'infini pour un float :

================================================================== > The macro INFINITY expands to a constant expression of type float
representing positive or unsigned infinity, if available; else to a
positive constant of type float that overflows at translation time.

In this case, using INFINITY will violate the constraint in 6.4.4 and
thus require a diagnostic.
================================================================== >
HUGE_VAL semble hélas être le meilleur compromis.

On peut cependant déterminer si l'infini est représentable avec :

#ifndef FP_INFINITE
// pas d'infini
#endif

D'après le rationale :

================================================================== > What is INFINITY on machines that do not support infinity? It should be
defined along the lines of: #define INFINITY 9e99999f, where there are
enough 9s in the exponent so that the value is too large to represent as
a float, hence, violates the constraint of 6.4.4 Constants.

In addition, the number classification macro FP_INFINITE should not be
defined. That allows an application to test for the existance of
FP_INFINITE as a safe way to determine if infinity is supported; this is
the feature test macro for support for infinity.
================================================================== >
<HS>
En C++, même combat, en plus expressif grâce à :
numeric_limits<float>::has_infinity.
et
numeric_limits<double>::has_infinity.
</HS>





Merci pour ces informations, je vais essayer de me débrouiller avec
cela...

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Marc
JKB wrote:

double x;
x = (double) INFINITY;

Ça fonctionne avec gcc et d'autres compilos C, mais le DEC C renacle
et renvoie une valeur absconse. D'où la question : est-ce que le fait
de caster INFINITY en double est portable ou non ?



Ça ne répond pas à la question, mais on trouve dans les headers de
solaris (quand il détecte que le compilateur est gcc) :

#define isinf(x) __extension__(
{ __typeof(x) __x_i = (x);
__x_i == (__typeof(__x_i)) INFINITY ||
__x_i == (__typeof(__x_i)) (-INFINITY); })

Donc c'est pratiqué ailleurs, ce cast de INFINITY dans le type flottant
qui va bien.
Avatar
espie
Si tu veux faire du bien defini, il faut se restreindre aux plateformes qui
ont un support IEEE 754 pour l'arithmetique flottante...

Si tu veux vraiment portable, il faut prendre en compte les autres plateformes.
Par exemple, vax.

Si tu n'as pas d'acces a un vrai vax, simh te permet de faire comme si...
http://simh.trailing-edge.com/
Avatar
JKB
Le Sun, 31 Jul 2011 12:04:23 +0000 (UTC),
Marc Espie écrivait :
Si tu veux faire du bien defini, il faut se restreindre aux plateformes qui
ont un support IEEE 754 pour l'arithmetique flottante...

Si tu veux vraiment portable, il faut prendre en compte les autres plateformes.
Par exemple, vax.

Si tu n'as pas d'acces a un vrai vax, simh te permet de faire comme si...
http://simh.trailing-edge.com/



J'ai déjà un OpenVMS 7.3 qui tourne dans un simh depuis très
longtemps, mais ce n'est pas vraiment utilisable : d'une part, le
idle loop n'est pas supporté (contrairement à la doc) et d'autre
part, il me manque les layered products pour avoir le compilo C...
Donc d'une part, ça fait énormément chauffer ma machine et d'autre
part, ça refuse de compiler ;-)

En fait, mon problème est sur mon AS800 qui tourne sous OpenVMS 8.3.
Le compilo est le DEC C et l'alpha est conforme au standard
IEEE-754 (et les options sont positionnées pour forcer ce mode) et
il y a bien un truc qui coince. Je ne peux pas continuer à tester
tout de suite, il faut d'abord que je change les DS1225 et 1287 qui
ont lâché... Quelle idée aussi de passer les patches d'OpenVMS et de
rebooter la machine...

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Antoine Leca
JKB écrivit :
Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



INFINITY ne peut jamais, dans le cas général, être totalement «propre».
Sur une machine où l'architecture ne permet de représenter un infini
comme valeur séparée, INFINITY doit être déclaré mais en tant que
constante qui provoque un avertissement destiné à attirer l'attention,
par exemple 1e99f (cf. 7.12p4 et surtout la note de bas de page).
Évidemment 1e99f est une très mauvaise valeur, même si c'est conforme.

Outre FP_CLASSIFY évoqué par Alexandre (bien vu!), on pourrait essayer
return HUGE_VAL > DBL_MAX ? INFINITY : DBL_MAX;
mais ce n'est pas parfait : on peut trouver probablement des
implémentations qui auront gardé HUGE_VAL=ÛL_MAX pour compatibilité
avec le « code existant », alors même que l'architecture a un infini
représentable et que la macro INFINITY est correctement déclarée :-(


Sinon, par analogie avec les fonctions existantes de la bibliothèque
standard (7.12.1p4, "if the mathematical result is an exact infinity
from finite arguments..."), retourner systématiquement la valeur
HUGE_VAL me semble être un comportement sensé à défaut d'être parfait.
Et c'est même portable avec C89 !


double x;
x = (double) INFINITY;



Je ne vois pas bien ce qu'apporte le transtypage.


Ça fonctionne avec gcc et d'autres compilos C, mais le DEC C renacle
et renvoie une valeur absconse. D'où la question : est-ce que le fait
de caster INFINITY en double est portable ou non ?



D'abord, sur une machine qui n'a pas d'infini représentable, cela va
donner une valeur (qui sera HUGE_VAL=ÛL_MAX si l'implémentation n'est
pas trop stupide) mais en même temps un avertissement ; est-ce que cela
rentre dans ta définition de « portable » ?

Sinon, l'infini est représentable, et en fonction de 6.3.1.5p1
When a float is promoted to double [...] its value is
unchanged (if the source value is represented in the
precision and range of its type).
et du fait que la norme n'envisage à aucun moment que l'infini simple
précision puisse être une valeur différente de l'infini double
précision, il semble que cela toute conversion de INFINITY en double (y
compris donc transtypage et affectation) doive être la représentation
double précision de l'infini (et rapport de bogue dans cas contraire).


Antoine
Avatar
JKB
Le Mon, 01 Aug 2011 10:33:46 +0200,
Antoine Leca écrivait :
JKB écrivit :
Je viens de tomber sur un problème amusant dans un bout de code et
je me demande si ce n'est pas un problème d'utilisation de la
constante INFINITY (code C99).

INFINITY est de type float. Comment retourner proprement une valeur
de type double ?



INFINITY ne peut jamais, dans le cas général, être totalement «propre».
Sur une machine où l'architecture ne permet de représenter un infini
comme valeur séparée, INFINITY doit être déclaré mais en tant que
constante qui provoque un avertissement destiné à attirer l'attention,
par exemple 1e99f (cf. 7.12p4 et surtout la note de bas de page).
Évidemment 1e99f est une très mauvaise valeur, même si c'est conforme.

Outre FP_CLASSIFY évoqué par Alexandre (bien vu!), on pourrait essayer
return HUGE_VAL > DBL_MAX ? INFINITY : DBL_MAX;
mais ce n'est pas parfait : on peut trouver probablement des
implémentations qui auront gardé HUGE_VAL=ÛL_MAX pour compatibilité
avec le « code existant », alors même que l'architecture a un infini
représentable et que la macro INFINITY est correctement déclarée :-(


Sinon, par analogie avec les fonctions existantes de la bibliothèque
standard (7.12.1p4, "if the mathematical result is an exact infinity
from finite arguments..."), retourner systématiquement la valeur
HUGE_VAL me semble être un comportement sensé à défaut d'être parfait.
Et c'est même portable avec C89 !


double x;
x = (double) INFINITY;



Je ne vois pas bien ce qu'apporte le transtypage.



Ici, effectivement, rien, si ce n'est certainement de rappeler au
dev que INFINITY est une constante de type float.

Ça fonctionne avec gcc et d'autres compilos C, mais le DEC C renacle
et renvoie une valeur absconse. D'où la question : est-ce que le fait
de caster INFINITY en double est portable ou non ?



D'abord, sur une machine qui n'a pas d'infini représentable, cela va
donner une valeur (qui sera HUGE_VAL=ÛL_MAX si l'implémentation n'est
pas trop stupide) mais en même temps un avertissement ; est-ce que cela
rentre dans ta définition de « portable » ?

Sinon, l'infini est représentable, et en fonction de 6.3.1.5p1
When a float is promoted to double [...] its value is
unchanged (if the source value is represented in the
precision and range of its type).
et du fait que la norme n'envisage à aucun moment que l'infini simple
précision puisse être une valeur différente de l'infini double
précision, il semble que cela toute conversion de INFINITY en double (y
compris donc transtypage et affectation) doive être la représentation
double précision de l'infini (et rapport de bogue dans cas contraire).



Merci pour cette précision.

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr