Enorme diferença.
Como o nome indica, a double
tem 2x a precisão de [1] . Em geral, a possui 15 dígitos decimais de precisão, enquanto que 7.float
double
float
Veja como o número de dígitos é calculado:
double
possui 52 bits de mantissa + 1 bit oculto: log (2 53 ) ÷ log (10) = 15,95 dígitos
float
possui 23 bits mantissa + 1 bit oculto: log (2 24 ) ÷ log (10) = 7,22 dígitos
Essa perda de precisão pode levar ao aumento de erros de truncamento quando cálculos repetidos são feitos, por exemplo,
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
enquanto
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Além disso, o valor máximo de float é de cerca de 3e38
, mas o dobro é de aproximadamente 1.7e308
, portanto, o uso float
pode atingir "infinito" (ou seja, um número de ponto flutuante especial) muito mais facilmente do que double
para algo simples, como calcular o fatorial de 60.
Durante o teste, talvez alguns casos de teste contenham esses números enormes, o que pode causar falhas nos programas se você usar flutuadores.
É claro que, às vezes, nem double
é preciso o suficiente, portanto, temos long double
[1] (o exemplo acima fornece 9.000000000000000066 no Mac), mas todos os tipos de ponto flutuante sofrem erros de arredondamento , portanto, se a precisão é muito importante (por exemplo, dinheiro processamento) você deve usar int
ou uma classe de fração.
Além disso, não use +=
para somar muitos números de ponto flutuante, pois os erros se acumulam rapidamente. Se você estiver usando Python, use fsum
. Caso contrário, tente implementar o algoritmo de somação Kahan .
[1]: Os padrões C e C ++ não especificam a representação de float
, double
e long double
. É possível que todos os três sejam implementados como IEEE de precisão dupla. No entanto, para a maioria das arquiteturas (gcc, MSVC; x86, x64, ARM) float
é de fato um número de ponto flutuante de precisão única IEEE (binary32) e double
é um número de ponto flutuante de precisão dupla IEEE (binary64).