46 votes

Double précision - décimales

D'après ce que j'ai lu, une valeur de type double a une précision approximative de 15 décimales. Cependant, lorsque j'utilise un nombre dont la représentation décimale se répète, comme 1,0/7,0, je constate que la variable contient la valeur 0,14285714285714285 - soit 17 positions (via le débogueur).

Je voudrais savoir pourquoi il est représenté comme 17 places en interne, et pourquoi une précision de 15 est toujours écrite à ~15 ?

43voto

Keith Thompson Points 85120

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.

18voto

trutheality Points 13261

Il s'agit en fait de 53 positions binaires, qui se traduisent par 15 positions décimales stables, ce qui signifie que si vous arrondissez un début avec un nombre à 15 positions décimales, vous le convertissez en un double et ensuite arrondir le double jusqu'à 15 décimales, vous obtiendrez le même chiffre. Pour représenter de manière unique un double vous avez besoin de 17 décimales (ce qui signifie que pour chaque nombre comportant 17 décimales, il existe une valeur unique la plus proche). double ), ce qui explique que 17 positions apparaissent, mais que tous les nombres à 17 décimales ne correspondent pas à des valeurs différentes. double (comme dans les exemples des autres réponses).

13voto

John Calsbeek Points 19381

La représentation décimale des nombres à virgule flottante est assez étrange. Si vous disposez d'un nombre à 15 décimales et que vous le convertissez en un nombre à virgule flottante, il est possible d'obtenir une représentation décimale. double puis l'imprimer avec exactement 15 décimales, vous devriez obtenir le même chiffre. D'un autre côté, si vous imprimez un nombre arbitraire de 15 décimales, vous devriez obtenir le même nombre. double avec 15 décimales et le reconvertir en un double vous n'obtiendrez pas nécessairement la même valeur en retour. 17 décimales pour cela. Et ni 15 ni 17 décimales ne suffisent pour afficher avec précision l'équivalent décimal exact d'un chiffre arbitraire double . En général, vous devez plus de 100 décimales pour faire cela précisément.

Voir la page Wikipédia sur la double-précision et ceci article sur la précision des points flottants .

8voto

Mooing Duck Points 27497

Un double contient 53 chiffres binaires avec précision, ce qui représente ~15,9545898 chiffres décimaux. Le débogueur peut afficher autant de chiffres qu'il le souhaite pour être plus précis à la binaire valeur. Ou il peut prendre moins de chiffres et binaire, tel que 0,1 prend 1 chiffre en base 10, mais infini en base 2.

C'est étrange, je vais donc vous montrer un exemple extrême. Si nous créons une valeur à virgule flottante super simple qui ne contient que 3 chiffres binaires de précision, sans mantisse ni signe (la plage est donc de 0-0,875), nos options sont les suivantes :

binary - decimal
000    - 0.000
001    - 0.125
010    - 0.250
011    - 0.375
100    - 0.500
101    - 0.625
110    - 0.750
111    - 0.875

Mais si vous faites les comptes, ce format n'est précis qu'à 0,903089987 chiffre décimal près. Même un chiffre n'est pas précis. Comme il est facile de le voir, puisqu'il n'y a pas de valeur commençant par 0.4?? ni 0.9?? et pourtant, pour afficher la précision totale, nous avons besoin de 3 chiffres décimaux.

tl;dr : Le débogueur vous montre la valeur de la variable variable à virgule flottante avec une précision arbitraire (19 chiffres dans votre cas), qui ne correspond pas nécessairement à la précision du format à virgule flottante (17 chiffres dans votre cas).

5voto

Jerry Coffin Points 237758

La virgule flottante IEEE 754 se fait en binaire. Il n'y a pas de conversion exacte d'un nombre donné de bits à un nombre donné de chiffres décimaux. 3 bits peuvent contenir des valeurs de 0 à 7, et 4 bits peuvent contenir des valeurs de 0 à 15. Une valeur de 0 à 9 prend à peu près 3,5 bits, mais ce n'est pas exact non plus.

Un nombre en double précision IEEE 754 occupe 64 bits. Sur ce nombre, 52 bits sont dédiés au significande (le reste est un bit de signe et un exposant). Puisque le significande est (généralement) normalisé, il y a une valeur implicite de 53%. rd bit.

Maintenant, avec 53 bits et environ 3,5 bits par chiffre, une simple division nous donne 15,1429 chiffres de précision. Mais n'oubliez pas que 3,5 bits par chiffre décimal n'est qu'une approximation, et non une réponse parfaitement précise.

Beaucoup (la plupart ?) des débogueurs regardent en fait le contenu du registre entier. Sur un x86, il s'agit en fait d'un nombre de 80 bits. L'unité à virgule flottante du x86 sera normalement ajustée pour effectuer des calculs avec une précision de 64 bits -- mais en interne, elle utilise en fait quelques "bits de garde", ce qui signifie essentiellement qu'en interne, elle effectue le calcul avec quelques bits de précision supplémentaires pour pouvoir arrondir le dernier chiffre correctement. Lorsque le débogueur examine l'ensemble du registre, il trouve généralement au moins un chiffre supplémentaire qui est raisonnablement précis - bien que ce chiffre n'ait pas de bits de garde, il peut ne pas être arrondi correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X