Je cherche des suggestions sur la façon de trouver les tailles (en bits) et la plage de nombres à virgule flottante d'une manière indépendante de l'architecture. Le code pourrait être construit sur différentes plates-formes (AIX, Linux, HPUX, VMS, peut-être Windoze) en utilisant différents drapeaux - les résultats devraient donc varier. Le signe, j'ai seulement vu comme un bit, mais comment mesurer la taille de l'exposant et la mantisse?Utilisation de C: Comment puis-je déterminer les tailles des composants d'un point flottant?
Répondre
Regardez les valeurs définies dans float.h
. Ceux-ci devraient vous donner les valeurs dont vous avez besoin.
Le nombre de bits utilisés pour stocker chaque champ dans un nombre à virgule flottante ne change pas.
Sign Exponent Fraction Bias
Single Precision 1 [31] 8 [30-23] 23 [22-00] 127
Double Precision 1 [63] 11 [62-52] 52 [51-00] 1023
EDIT: Comme l'a souligné Jonathan dans les commentaires, je laisse le type long double. Je vais laisser sa décomposition des bits comme un exercice pour le lecteur. :)
Puisque vous envisagez de construire pour un certain nombre de systèmes, je pense que vous pourriez envisager d'utiliser GCC pour la compilation.
Quelques bonnes infos sur virgule flottante - c'est ce que presque toutes les architectures modernes utilisent: http://en.wikipedia.org/wiki/IEEE_754
Ce détail quelques-unes des différences qui peuvent venir http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html
Comme vous suivez les liens suggérés dans les précédents commentaires, vous verrez probablement des références à What Every Computer Scientist Should Know About Floating Point Arithmetic. Par tous les moyens, prenez le temps de lire ce document. Il apparaît partout lorsque le point flottant est discuté.
Son relativement facile à trouver:
décimal ou binaire;
myfloat a = 2.0,
b = 0.0;
for (int i=0; i<20; i++)
b += 0.1;
(a == b) => decimal, else binary
Raison: Tous les systèmes binaires peuvent représenter 2.0, mais tout système binaire auront un terme d'erreur pour représenter 0,1. En accumulant vous pouvez être sûr que ce terme d'erreur ne disparaîtra pas comme en arrondissant: par ex. 1.0 == 3.0 * (1.0/3.0), même dans les systèmes binaires
longueur Mantisse:
Myfloat a = 1.0,
b = 1.0,
c,
inc = 1.0;
int mantissabits = 0;
do {
mantissabits++;
inc *= 0.5; // effectively shift to the right
c = b+inc;
} while (a != c);
Vous ajoutez la baisse des termes jusqu'à la capacité de la mantisse. Il renvoie 24 bits pour float et 53 bits pour double ce qui est correct (La mantisse elle-même ne contient que 23/52 bits, mais comme le premier bit est toujours un sur les valeurs normalisées, vous avez un bit supplémentaire caché).
longueur Exponent:
Myfloat a = 1.0;
int max = 0,
min = 0;
while (true) {
a *= 2.0;
if (a != NaN && a != Infinity && whatever) // depends on system
max++;
else
break;
}
a = 1.0;
while (true) {
a *= 0.5;
if (a != 0.0)
min--;
else
break;
}
Vous décalez 1.0 vers la gauche ou vers la droite jusqu'à ce que vous appuyez sur le haut ou le bas. Normalement, la plage d'exp est -(max+1) - max
.
Si min
est inférieur à -(max+1)
, vous avez (sous forme de flottants et de doubles) des sous-normales. Les valeurs normalement positives et négatives sont symétriques (avec peut-être un décalage), mais vous pouvez ajuster le test en ajoutant des valeurs négatives.
Non vrai, pour certaines valeurs de true; ^) ~ Il existe un petit nombre de plates-formes qui n'utilisent pas IEEE754. Mais pour la plupart, vous êtes bien sûr correct. –
Vous avez manqué un long double. –
@Don: * Très * petites valeurs de vrai. :) –