Un double IEEE possède 53 bits significatifs (c'est la valeur de DBL_MANT_DIG
en <cfloat>
). Cela représente environ 15,95 chiffres décimaux (log10(2 53 )) ; la mise en œuvre définit DBL_DIG
à 15, pas à 16, car il doit arrondir à l'inférieur. Vous disposez donc d'une précision de près d'un chiffre décimal supplémentaire (au-delà de ce qu'implique l'expression DBL_DIG==15
) à cause de cela.
El nextafter()
calcule le nombre représentable le plus proche d'un nombre donné ; elle peut être utilisée pour montrer la précision d'un nombre donné.
Ce programme :
#include <cstdio>
#include <cfloat>
#include <cmath>
int main() {
double x = 1.0/7.0;
printf("FLT_RADIX = %d\n", FLT_RADIX);
printf("DBL_DIG = %d\n", DBL_DIG);
printf("DBL_MANT_DIG = %d\n", DBL_MANT_DIG);
printf("%.17g\n%.17g\n%.17g\n", nextafter(x, 0.0), x, nextafter(x, 1.0));
}
me donne cette sortie sur mon système :
FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.14285714285714282
0.14285714285714285
0.14285714285714288
(Vous pouvez remplacer %.17g
par, disons, %.64g
pour voir plus de chiffres, dont aucun n'est significatif).
Comme vous pouvez le constater, le dernier chiffre décimal affiché change par 3 à chaque valeur consécutive. Le fait que le dernier chiffre affiché de 1.0/7.0
( 5
) correspond à la valeur mathématique est en grande partie une coïncidence ; c'était un coup de chance. Et la valeur correcte arrondi le chiffre est 6
pas 5
. Remplacement de 1.0/7.0
por 1.0/3.0
donne cette sortie :
FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.33333333333333326
0.33333333333333331
0.33333333333333337
qui montre environ 16 chiffres décimaux de précision, comme on peut s'y attendre.