La norme C ++ spécifie-t-elle quelque chose sur la représentation des nombres à virgule flottante?

Pour les types T pour lesquels std::is_floating_point::value est true , la norme C ++ spécifie-t-elle quoi que ce soit sur la manière dont T doit être implémenté?

Par exemple, T doit-il même suivre une représentation signe / mantisse / exposant? Ou peut-il être complètement arbitraire?

À partir de N3337:

[basic.fundamental/8]: Il existe trois types de virgule flottante: float, double et long double. Le type double fournit au moins autant de précision que float et le type long double fournit au moins autant de précision que double. L’ensemble de valeurs du type float est un sous-ensemble de l’ensemble de valeurs du type double; l’ensemble de valeurs du type double est un sous-ensemble de l’ensemble des valeurs du type long double. La représentation des valeurs des types à virgule flottante est définie par l’implémentation . Les types intégral et flottant sont collectivement appelés types arithmétiques. Les spécialisations du modèle standard std :: numeric_limits (18.3) doivent spécifier les valeurs maximales et minimales de chaque type arithmétique pour une implémentation.

Si vous voulez vérifier si votre implémentation utilise IEEE-754, vous pouvez utiliser std::numeric_limits::is_iec559 :

 static_assert(std::numeric_limits::is_iec559, "This code requires IEEE-754 doubles"); 

Il existe un certain nombre d’autres caractéristiques d’assistance dans ce domaine, telles que has_infinity , quiet_NaN et plus .

La norme C comporte une “annexe” (en C11 l’annexe F) qui explique ce qu’une implémentation de C est conforme à la norme CEI 60559, la norme suivante de la norme IEEE 754. Une implémentation conforme à l’Annexe F doit comporter IEEE -représentation nombres à virgule flottante. Cependant, la mise en œuvre de cette annexe est facultative; la norme de base évite spécifiquement de dire quoi que ce soit à propos de la représentation des nombres à virgule flottante.

Je ne sais pas s’il existe une annexe équivalente pour C ++. Cela n’apparaît pas dans le N3337, mais cela pourrait signifier qu’il est dissortingbué séparément. L’existence de std::numeric_limits::is_iec559 indique que le comité C ++ a au moins réfléchi à cela, mais peut-être pas avec autant de détails que le comité C. (Il est et a toujours été dommage que la norme C ++ ne soit pas exprimée sous la forme d’un ensemble de modifications apscopes à la norme C.)

Aucune implémentation particulière n’est requirejse. La norme C ++ n’en parle pas beaucoup. La norme C donne beaucoup de détails sur le modèle conceptuel utilisé pour les nombres à virgule flottante, avec un signe, un exposant, une signification dans une base b , etc. Toutefois, il est expressément indiqué qu’il s’agit d’une information purement descriptive et non impérative (C11, note 21):

Le modèle à virgule flottante est destiné à clarifier la description de chaque caractéristique à virgule flottante et n’exige pas que l’arithmétique à virgule flottante de la mise en œuvre soit identique.

Cela dit, même si les détails peuvent varier, il me semble au moins de prime abord qu’il serait difficile de produire (par exemple) une mise en œuvre conforme du double qui ne cadrait pas assez avec le modèle habituel (c.-à-d. Un significatif et un exposant). ou du moins difficile à faire avec une performance compétitive, de toute façon). Cependant, il ne serait pas particulièrement difficile de le faire varier d’autres manières, telles que la réorganisation de l’ordre ou l’utilisation d’une base différente.

La définition de std::numeric_limits::digits (et std::numeric_limits::digits10 ) implique assez directement que ce qui est répertorié en tant que type à virgule flottante doit conserver (au moins approximativement) la même précision pour tous les nombres dans un assez large éventail de magnitudes. Le moyen le plus évident d’y parvenir consiste à atsortingbuer un certain nombre de bits / chiffres à un significande et un autre ensemble (séparé) de bits à un exposant.

L’idée de std::is_floating_point est de faire en sorte que le code utilisateur d’origine différente fonctionne mieux ensemble. Techniquement, vous pouvez spécifier un int tant que std::is_floating_point sans provoquer de comportement indéfini. Mais disons que vous avez une bibliothèque basée sur un modèle qui doit être divisée à plusieurs resockets par T n . Pour accélérer les choses, la bibliothèque crée un T ni = 1 / n et remplace la division par n par la multiplication par ni . Cela fonctionne très bien pour les nombres à virgule flottante, mais échoue pour les entiers. Par conséquent, la bibliothèque ne fait correctement l’optimisation que si std::is_floating_point::value == true . Si vous mentez, le code fonctionne probablement toujours du sharepoint vue de la norme, mais il est incorrect du sharepoint vue logique. Donc, si vous écrivez une classe qui se comporte comme un grand float marquez-la comme étant std::is_floating_point , sinon ne le faites pas. Cela devrait vous permettre d’obtenir le code optimal et correct.