Quelle est la différence entre float et double?

j'ai lu la différence entre la double précision et la simple précision. Toutefois, dans la plupart des cas, float et double semblent interchangeables, c/" class="blnk">c'est-à-dire que l'utilisation de l'un ou de l'autre ne semble pas affecter les résultats. Est-ce vraiment le cas? Quand les flotteurs et les doubles sont-ils interchangeables? Quelles sont les différences entre eux?

333
demandé sur nbro 2010-03-05 15:48:32

11 réponses

énorme différence.

comme son nom l'indique, un double a 2x la précision de float [1] . En général, un double a 15 chiffres décimaux de précision, tandis que float a 7.

Voici comment le nombre de chiffres sont calculés:

double possède 52 bits mantissa + 1 bit caché: log(2 53 ) ś log(10) = 15.95 chiffres

float a 23 bits de mantissa + 1 bit caché: log(2 24 )÷log (10) = 7.22 chiffres

cette perte de précision pourrait conduire à des erreurs de troncature beaucoup plus faciles à flotter, 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

aussi, la valeur maximale du flotteur est d'environ 3e38 , mais double est d'environ 1.7e308 , donc l'utilisation de float peut frapper" infinity "(c.-à-d. un nombre flottant spécial) beaucoup plus facilement que double pour quelque chose de simple, par exemple en calculant le factoriel de 60.

pendant les tests, peut-être que quelques cas de test contiennent ces énormes nombres, qui peuvent causer l'échec de vos programmes si vous utilisez des flotteurs.


bien sûr, parfois, même double n'est pas assez précis, donc nous avons parfois long double [1] (l'exemple ci-dessus donne 9.000000000000000066 sur Mac), mais tous les types de point flottant souffrent de erreurs de arrondi , donc si la précision est très importante (par exemple le traitement de l'argent), vous devez utiliser int ou une classe de fraction.


de plus, n'utilisez pas += pour additionner des lots 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 précisent pas la représentation de float , double et long double . Il est possible que les trois soient mis en œuvre comme double précision IEEE. Néanmoins, pour la plupart des architectures (gcc, MSVC; x86, x64, ARM) float est en effet un IEEE nombre de virgule flottante de précision simple (binary32), et double est un nombre de virgule flottante de précision double IEEE (binary64).

407
répondu kennytm 2018-03-10 10:55:48

voici ce que disent les normes C99 (ISO-CEI 9899 6.2.5 §10) ou C++2003 (ISO-CEI 14882-2003 3.1.9 §8):

il existe trois types de virgule flottante: float , double et long double . Le type double fournit au moins autant de précision que float , et le type long double fournit au moins autant de précision que double . L'ensemble des valeurs du type float est un sous-ensemble de l'ensemble de valeurs de le type double ; l'ensemble des valeurs du type double est un sous-ensemble de l'ensemble des valeurs du type long double .

le standard C++ ajoute:

la représentation de la valeur des types à virgule flottante est définie par la mise en œuvre.

je suggère d'avoir un regard sur l'excellent ce que tout informaticien devrait savoir sur L'arithmétique flottante qui couvre la norme IEEE en profondeur. Vous en apprendrez plus sur les détails de la représentation et vous réaliserez qu'il y a un compromis entre la magnitude et la précision. La précision de la représentation en virgule flottante augmente avec la diminution de la grandeur, donc les nombres en virgule flottante entre -1 et 1 sont ceux avec la plus grande précision.

50
répondu Gregory Pakosz 2010-03-06 17:29:32

é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 et double , nous pouvons écrire un programme de test:

#include <stdio.h>
#include <math.h>

void dbl_solve(double a, double b, double c)
{
    double d = b*b - 4.0*a*c;
    double sd = sqrt(d);
    double r1 = (-b + sd) / (2.0*a);
    double r2 = (-b - sd) / (2.0*a);
    printf("%.5f\t%.5f\n", r1, r2);
}

void flt_solve(float a, float b, float c)
{
    float d = b*b - 4.0f*a*c;
    float sd = sqrtf(d);
    float r1 = (-b + sd) / (2.0f*a);
    float r2 = (-b - sd) / (2.0f*a);
    printf("%.5f\t%.5f\n", r1, r2);
}   

int main(void)
{
    float fa = 1.0f;
    float fb = -4.0000000f;
    float fc = 3.9999999f;
    double da = 1.0;
    double db = -4.0000000;
    double dc = 3.9999999;
    flt_solve(fa, fb, fc);
    dbl_solve(da, db, dc);
    return 0;
}  

l'Exécution de l' programme me donne:

2.00000 2.00000
2.00032 1.99968

notez que les nombres ne sont pas grands, mais vous obtenez quand même des effets d'Annulation en utilisant float .

(en fait, ce qui précède n'est pas la meilleure façon de résoudre les équations quadratiques en utilisant soit des nombres à virgule flottante de précision simple ou double, mais la réponse reste inchangée même si on utilise une méthode plus stable .)

24
répondu Alok Singhal 2010-03-05 17:57:25
  • Un double est de 64 et de simple précision (float) est de 32 bits.
  • le double a un plus grand mantissa (les bits entiers du nombre réel).
  • toutes les inexactitudes seront plus petites dans le double.
18
répondu graham.reeds 2010-03-05 12:53:20

la taille des nombres impliqués dans les calculs du point de flottaison n'est pas la chose la plus pertinente. C'est le calcul qui est effectué.

essentiellement, si vous effectuez un calcul et que le résultat est un nombre irrationnel ou décimal récurrent, alors il y aura des erreurs d'arrondissement lorsque ce nombre est écrasé dans la structure de données de taille finie que vous utilisez. Comme double est deux fois la taille de flotteur, alors l'erreur d'arrondi sera beaucoup plus petit.

les tests peuvent utiliser spécifiquement des nombres qui causeraient ce genre d'erreur et donc testé que vous avez utilisé le type approprié dans votre code.

11
répondu Dolbz 2018-03-10 11:05:03
Les flotteurs

sont moins précis que les flotteurs doubles. Bien que vous le sachiez déjà, lisez ce que nous devrions savoir sur L'arithmétique à virgule flottante pour une meilleure compréhension.

8
répondu N 1.1 2010-03-05 13:09:51
Flotteur de type

, 32 bits de long, a une précision de 7 chiffres. Alors qu'il peut stocker des valeurs avec très grande ou très petite gamme (+/- 3.4 * 10 ^ 38 ou * 10^-38), il ne comporte que 7 chiffres significatifs.

type double, 64 bits de long, a une plus grande portée (*10^+/-308) et une précision de 15 chiffres.

type long double est nominalement 80 bits, bien qu'un compilateur/OS appariement donné peut stocker 12-16 octets pour des fins d'alignement. Le long double a un exposant qui juste ridiculement énorme et devrait avoir la précision de 19 chiffres. Microsoft, dans leur sagesse infinie, limite le double long à 8 octets, le même que le double simple.

Généralement parlant, il suffit d'utiliser le type double quand vous avez besoin d'une valeur/variable à virgule flottante. Les valeurs en virgule flottante littérale 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 renvoient des doubles. Vous vous épargnerez bien des maux de tête et des typographies si vous juste utiliser des doubles.

8
répondu Humble Coder 2017-11-17 23:29:38

je viens de tomber sur une erreur qui m'a pris une éternité à comprendre et peut potentiellement vous donner un bon exemple de précision.

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}

la sortie est

0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999

comme vous pouvez le voir après 0.83, la précision diminue considérablement.

cependant, si je mets en place t comme double, un tel problème ne se produira pas.

il m'a fallu cinq heures pour réaliser cette petite erreur, qui a ruiné mon programme.

7
répondu Elliscope Fang 2018-03-10 11:06:08

lorsque vous utilisez des nombres à virgule flottante, vous ne pouvez pas croire que vos tests locaux seront exactement les mêmes que ceux qui sont effectués du côté du serveur. L'environnement et le compilateur sont probablement différents sur votre système local et où les tests finaux sont effectués. J'ai vu ce problème de nombreuses fois dans certaines compétitions de TopCoder, surtout si vous essayez de comparer deux nombres à virgule flottante.

3
répondu Tuomas Pelkonen 2010-03-05 13:00:57

les opérations de comparaison intégrées diffèrent comme dans quand vous comparez 2 nombres avec point flottant, la différence dans le type de données (c.-à-d. flottant ou double) peut entraîner des résultats différents.

2
répondu Johnathan Lau 2012-11-05 01:35:45

contrairement à un int (nombre entier), un float ont un point décimal, et ainsi peut un double . Mais la différence entre les deux est qu'un double est deux fois plus détaillé qu'un float , ce qui signifie qu'il peut avoir le double de la quantité de nombres après le point décimal.

-1
répondu Nykal 2017-09-05 12:10:09