Differenza enorme.
Come suggerisce il nome, a double
ha una precisione doppia di [1] . In generale a ha 15 cifre decimali di precisione, mentre ha 7.float
double
float
Ecco come vengono calcolati il numero di cifre:
double
ha 52 bit mantissa + 1 bit nascosto: log (2 53 ) ÷ log (10) = 15,95 cifre
float
ha 23 bit mantissa + 1 bit nascosto: log (2 24 ) ÷ log (10) = 7,22 cifre
Questa perdita di precisione potrebbe comportare l'accumulo di maggiori errori di troncamento quando si eseguono calcoli ripetuti, ad es
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
mentre
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Inoltre, il valore massimo di float è circa 3e38
, ma doppio è circa 1.7e308
, quindi l'utilizzo float
può colpire "infinito" (cioè uno speciale numero in virgola mobile) molto più facilmente rispetto double
a qualcosa di semplice, ad esempio calcolare il fattoriale di 60.
Durante il test, forse alcuni casi di test contengono questi numeri enormi, che possono causare il fallimento dei programmi se si utilizzano float.
Certo, a volte, anche double
non è abbastanza preciso, quindi a volte abbiamo long double
[1] (l'esempio sopra fornisce 9.000000000000000066 su Mac), ma tutti i tipi in virgola mobile soffrono di errori di arrotondamento , quindi se la precisione è molto importante (ad es. Denaro elaborazione) è necessario utilizzare int
o una classe di frazione.
Inoltre, non utilizzare +=
per sommare molti numeri in virgola mobile, poiché gli errori si accumulano rapidamente. Se stai usando Python, usa fsum
. Altrimenti, prova a implementare l' algoritmo di somma Kahan .
[1]: la C e C ++ standard non specificano la rappresentazione di float
, double
e long double
. È possibile che tutti e tre siano implementati come doppia precisione IEEE. Tuttavia, per la maggior parte delle architetture (gcc, MSVC; x86, x64, ARM) float
è effettivamente un numero in virgola mobile a precisione singola IEEE (binary32), ed double
è un numero in virgola mobile a precisione doppia IEEE (binary64).