Précision 'float' vs 'double'

155

Le code

float x  = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);

vous donnera la sortie

x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116

où sur la troisième ligne de sortie 741012573242est garbage et sur la quatrième ligne 116est garbage. Les doubles ont-ils toujours 16 chiffres significatifs alors que les flotteurs ont toujours 7 chiffres significatifs? Pourquoi les doubles n'ont-ils pas 14 chiffres significatifs?

toto
la source

Réponses:

146

Les nombres à virgule flottante en C utilisent le codage IEEE 754 .

Ce type d'encodage utilise un signe, un significande et un exposant.

En raison de ce codage, de nombreux nombres auront de petits changements pour leur permettre d'être stockés.

En outre, le nombre de chiffres significatifs peut changer légèrement car il s'agit d'une représentation binaire et non décimale.

La précision simple (float) vous donne 23 bits de significande, 8 bits d'exposant et 1 bit de signe.

La double précision (double) vous donne 52 bits de significande, 11 bits d'exposant et 1 bit de signe.

Alan Geleynse
la source
4
C99 le fait, auparavant c'était au compilateur.
Alan Geleynse
21
-1 Cette déclaration est manifestement fausse: "En raison de ce codage, vous ne pouvez jamais garantir que vous n'aurez pas de changement dans votre valeur."
R .. GitHub STOP HELPING ICE
16
@Alan: C99 ne nécessite pas de virgule flottante IEEE; il le recommande simplement.
R .. GitHub STOP HELPING ICE
4
@Alan: R .. est correct; L'Annexe F (qui spécifie les liaisons IEEE-754) est normative, mais seulement en vigueur si une implémentation le définit __STDC_IEC_559__. Une implémentation qui ne définit pas cette macro est libre de ne pas se conformer à IEEE-754.
Stephen Canon
12
@Alan: Sous IEEE 754, il est facilement garanti qu'il n'y a pas de changement dans les valeurs 0.5, 0.046875ou 0.376739501953125par rapport à leurs représentations décimales. (Ce sont tous des rationnels diadiques avec le numérateur ajusté dans la mantisse et le logarithme en base 2 du dénominateur ajusté dans l'exposant.)
R .. GitHub STOP HELPING ICE
42

Les doubles ont-ils toujours 16 chiffres significatifs alors que les flotteurs ont toujours 7 chiffres significatifs?

Non. Les doubles ont toujours 53 bits significatifs et les flottants ont toujours 24 bits significatifs (sauf pour les dénormaux, les infinis et les valeurs NaN, mais ce sont des sujets pour une question différente). Ce sont des formats binaires, et vous ne pouvez parler clairement de la précision de leurs représentations qu'en termes de chiffres binaires (bits).

Ceci est analogue à la question de savoir combien de chiffres peuvent être stockés dans un entier binaire: un entier 32 bits non signé peut stocker des entiers jusqu'à 32 bits, ce qui ne correspond pas précisément à un nombre de chiffres décimaux: tous les nombres entiers jusqu'à 9 chiffres décimaux peuvent être stockés, mais un grand nombre de nombres à 10 chiffres peuvent également être stockés.

Pourquoi les doubles n'ont-ils pas 14 chiffres significatifs?

Le codage d'un double utilise 64 bits (1 bit pour le signe, 11 bits pour l'exposant, 52 bits significatifs explicites et un bit implicite), soit le double du nombre de bits utilisés pour représenter un flottant (32 bits).

Stephen Canon
la source
15

float: 23 bits de significande, 8 bits d'exposant et 1 bit de signe.

double: 52 bits de significande, 11 bits d'exposant et 1 bit de signe.

abe312
la source
11

Il est généralement basé sur des chiffres significatifs de l'exposant et du significand en base 2, pas en base 10. D'après ce que je peux dire dans la norme C99, cependant, il n'y a pas de précision spécifiée pour les flottants et les doubles (à part le fait que 1 et 1 + 1E-5/ 1 + 1E-7se distinguent [ floatet de manière représentative double]). Cependant, le nombre de chiffres significatifs est laissé à l'implémenteur (ainsi que la base qu'ils utilisent en interne, donc en d'autres termes, une implémentation pourrait décider de le faire sur la base de 18 chiffres de précision en base 3). [1]

Si vous avez besoin de connaître ces valeurs, les constantes FLT_RADIXet FLT_MANT_DIG(et DBL_MANT_DIG/ LDBL_MANT_DIG) sont définies dans float.h.

La raison pour laquelle on l'appelle a doubleest que le nombre d'octets utilisés pour le stocker est le double du nombre d'un flottant (mais cela inclut à la fois l'exposant et le significand). La norme IEEE 754 (utilisée par la plupart des compilateurs) alloue relativement plus de bits pour le significande que pour l'exposant (23 à 9 pour floatcontre 52 à 12 pour double), c'est pourquoi la précision est plus que doublée.

1: Section 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )

user470379
la source
Faute de frappe? C89 nécessite un epsilon d'au plus 1E-9pour double, non 1E-7.
Rufflewind
10

Un flotteur a 23 bits de précision et un double en a 52.

Chris Nash
la source
Détail: binary64 a un 53 bits significatif (52 explicitement stocké) binary32 a 24 bits (23 explicitement stocké).
chux - Réintégrer Monica le
4

Ce n'est pas exactement une double précision à cause du fonctionnement de l' IEEE 754 et du fait que le binaire ne se traduit pas vraiment bien en décimal. Jetez un œil à la norme si cela vous intéresse.

user541686
la source
4

float signifie nombre à virgule flottante. En C, le type de données float est utilisé dans les cas où la précision du nombre total de chiffres est 7. Par exemple: - le no décimal. 12.3546987 ne peut pas être stocké dans float car il a un total de 9 chiffres.La sortie sera affichée comme 12.354699 c'est-à-dire que les 7 premiers chiffres seront affichés comme saisis dans l'entrée et le 8ème chiffre sera arrondi.Le type float peut représenter des valeurs allant d'environ 1,5 x 10 ^ (- 45) à 3,4 x 10 ^ (38) .En termes d'allocation de mémoire, float est un type de données à virgule flottante 32 bits simple précision.

Contrairement à float, double a une précision de 15 à 16 chiffres, la plage de double est de 5,0 × 10 ^ (- 345) à 1,7 × 10 ^ (308) .En termes d'allocation d'octets, double est une donnée à virgule flottante de 64 bits type.

Le problème se pose dans son utilisation.float ou double n'affecte pas printf mais en cas de scanf le type de données approprié doit être utilisé en fonction du nombre total. de chiffres en flottant no. qui doit être lu à partir de l'entrée.

Par conséquent, le double est préféré au flottant pour une plus grande précision des données.

J'espère que cela t'aides.

Vineeth Krishna K
la source