Énorme différence.
Comme son nom l'indique, a double
a 2x la précision de [1] . En général, a a 15 chiffres décimaux de précision, alors qu'il en a 7.float
double
float
Voici comment le nombre de chiffres est calculé:
double
a 52 bits de mantisse + 1 bit caché: log (2 53 ) ÷ log (10) = 15,95 chiffres
float
a 23 bits de mantisse + 1 bit caché: log (2 24 ) ÷ log (10) = 7,22 chiffres
Cette perte de précision pourrait entraîner une accumulation d'erreurs de troncature plus importantes lorsque des calculs répétés sont effectués, par exemple
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
tandis que
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
De plus, la valeur maximale de float est d'environ 3e38
, mais le double est d'environ 1.7e308
, donc l'utilisation float
peut frapper "l'infini" (c'est-à-dire un nombre spécial à virgule flottante) beaucoup plus facilement que double
pour quelque chose de simple, par exemple le calcul de la factorielle de 60.
Pendant les tests, quelques cas de test contiennent peut-être ces énormes nombres, ce qui peut entraîner l'échec de vos programmes si vous utilisez des flottants.
Bien sûr, parfois, même double
pas assez précis, nous avons donc parfois long double
[1] (l'exemple ci-dessus donne 9.000000000000000066 sur Mac), mais tous les types à virgule flottante souffrent d' erreurs d' arrondi , donc si la précision est très importante (par exemple, l'argent vous devez utiliser int
ou une classe de fraction.
De plus, ne pas utiliser +=
pour additionner beaucoup de nombres à virgule flottante, car les erreurs s'accumulent rapidement. Si vous utilisez Python, utilisez fsum
. Sinon, essayez d'implémenter l' algorithme de sommation de Kahan .
[1]: Les normes C et C ++ ne spécifient pas la représentation de float
, double
et long double
. Il est possible que les trois soient implémentés en double précision IEEE. Néanmoins, pour la plupart des architectures (gcc, MSVC; x86, x64, ARM) float
est en effet un nombre à virgule flottante simple précision IEEE (binaire32), et double
est un nombre à virgule flottante double précision IEEE (binaire64).
Voici ce que disent les normes C99 (ISO-IEC 9899 6.2.5 §10) ou C ++ 2003 (ISO-IEC 14882-2003 3.1.9 §8):
La norme C ++ ajoute:
Je suggérerais de jeter un coup d'œil à l'excellent ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante qui couvre en profondeur la norme à virgule flottante IEEE. Vous en apprendrez plus sur les détails de la représentation et vous vous rendrez compte qu'il existe un compromis entre la magnitude et la précision. La précision de la représentation en virgule flottante augmente à mesure que l'amplitude diminue, donc les nombres en virgule flottante entre -1 et 1 sont ceux qui ont le plus de précision.
la source
Étant donné une équation quadratique: x 2 - 4.0000000 x + 3.9999999 = 0, les racines exactes à 10 chiffres significatifs sont, r 1 = 2.000316228 et r 2 = 1.999683772.
En utilisant
float
etdouble
, nous pouvons écrire un programme de test:L'exécution du programme me donne:
Notez que les nombres ne sont pas importants, mais vous obtenez toujours des effets d'annulation en utilisant
float
.(En fait, ce qui précède n'est pas le meilleur moyen de résoudre des équations quadratiques en utilisant des nombres à virgule flottante simple ou double précision, mais la réponse reste inchangée même si l'on utilise une méthode plus stable .)
la source
la source
La taille des nombres impliqués dans les calculs en virgule flottante n'est pas la chose la plus pertinente. C'est le calcul qui est effectué qui est pertinent.
En gros, si vous effectuez un calcul et que le résultat est un nombre irrationnel ou décimal récurrent, il y aura des erreurs d'arrondi lorsque ce nombre sera écrasé dans la structure de données de taille finie que vous utilisez. Étant donné que le double est deux fois la taille du flottant, l'erreur d'arrondi sera beaucoup plus petite.
Les tests peuvent spécifiquement utiliser des nombres qui provoqueraient ce type d'erreur et ont donc testé que vous aviez utilisé le type approprié dans votre code.
la source
Le type float, long de 32 bits, a une précision de 7 chiffres. Bien qu'il puisse stocker des valeurs avec une plage très grande ou très petite (+/- 3,4 * 10 ^ 38 ou * 10 ^ -38), il n'a que 7 chiffres significatifs.
Le type double, 64 bits de long, a une plus grande plage (* 10 ^ + / - 308) et une précision de 15 chiffres.
Le type long double est nominalement de 80 bits, bien qu'un appariement compilateur / OS donné puisse le stocker en tant que 12-16 octets à des fins d'alignement. Le long double a un exposant qui est ridiculement énorme et devrait avoir une précision de 19 chiffres. Microsoft, dans sa sagesse infinie, limite le double long à 8 octets, le même que le double simple.
De manière générale, utilisez simplement type double lorsque vous avez besoin d'une valeur / variable à virgule flottante. Les valeurs littérales en virgule flottante utilisées dans les expressions seront traitées comme des doubles par défaut, et la plupart des fonctions mathématiques qui renvoient des valeurs en virgule flottante retournent des doubles. Vous vous épargnerez de nombreux maux de tête et transtypages si vous utilisez simplement le double.
la source
Je viens de rencontrer une erreur qui m'a pris une éternité à comprendre et peut potentiellement vous donner un bon exemple de précision de flottement.
La sortie est
Comme vous pouvez le voir après 0,83, la précision diminue considérablement.
Cependant, si je configure en
t
tant que double, un tel problème ne se produira pas.Il m'a fallu cinq heures pour réaliser cette erreur mineure, qui a ruiné mon programme.
la source
double
n'est pas une bonne solution ici. Vous utilisezint
pour compter et faire une multiplication interne pour obtenir votre valeur à virgule flottante.Les flotteurs ont moins de précision que les doubles. Bien que vous le sachiez déjà, lisez ce que nous devons savoir sur l'arithmétique à virgule flottante pour une meilleure compréhension.
la source
Lorsque vous utilisez des nombres à virgule flottante, vous ne pouvez pas être sûr que vos tests locaux seront exactement les mêmes que ceux effectués côté serveur. L'environnement et le compilateur sont probablement différents sur votre système local et où les tests finaux sont exécutés. J'ai vu ce problème plusieurs fois auparavant dans certaines compétitions TopCoder, surtout si vous essayez de comparer deux nombres à virgule flottante.
la source
Les opérations de comparaison intégrées diffèrent comme lorsque vous comparez 2 nombres à virgule flottante, la différence de type de données (c'est-à-dire flottant ou double) peut entraîner des résultats différents.
la source
Si l'on travaille avec un traitement intégré, le matériel sous-jacent (par exemple, FPGA ou un modèle de processeur / microcontrôleur spécifique) sera implémenté de manière optimale dans le matériel, tandis que le double utilisera des routines logicielles. Donc, si la précision d'un float est suffisante pour gérer les besoins, le programme s'exécutera quelques fois plus rapidement avec float puis doublera. Comme indiqué dans d'autres réponses, méfiez-vous des erreurs d'accumulation.
la source
Contrairement à un
int
(nombre entier), afloat
a un point décimal, tout comme adouble
. Mais la différence entre les deux est que adouble
est deux fois plus détaillé que afloat
, ce qui signifie qu'il peut avoir le double du nombre de chiffres après la virgule décimale.la source