Duża różnica.
Jak sama nazwa wskazuje, a doublema 2x precyzję [1] . Ogólnie rzecz biorąc a ma 15 cyfr dziesiętnych precyzji, a ma 7.floatdoublefloat
Oto jak obliczana jest liczba cyfr:
doublema 52 bity mantysy + 1 ukryty bit: log (2 53 ) ÷ log (10) = 15,95 cyfr
floatma 23 bity mantysy + 1 ukryty bit: log (2 24 ) ÷ log (10) = 7,22 cyfry
Ta utrata precyzji może prowadzić do gromadzenia większych błędów skracania, gdy wykonywane są powtarzane obliczenia, np
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
podczas
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Ponadto maksymalna wartość liczby zmiennoprzecinkowej wynosi około 3e38, ale wartość podwójna wynosi około 1.7e308, więc użycie floatmoże osiągnąć „nieskończoność” (tj. Specjalną liczbę zmiennoprzecinkową) o wiele łatwiej niż w doubleprzypadku czegoś prostego, np. Obliczenie silni 60.
Podczas testowania może kilka przypadków testowych zawiera te ogromne liczby, co może spowodować awarię programów, jeśli używasz liczb zmiennoprzecinkowych.
Oczywiście czasami nawet doublenie jest wystarczająco dokładna, dlatego czasami mamy long double[1] (powyższy przykład podaje 9.000000000000000066 na Macu), ale wszystkie typy zmiennoprzecinkowe cierpią na błędy zaokrąglania , więc jeśli precyzja jest bardzo ważna (np. Pieniądze przetwarzanie) należy użyć intlub klasy ułamkowej.
Ponadto nie należy używać +=do sumowania wielu liczb zmiennoprzecinkowych, ponieważ błędy kumulują się szybko. Jeśli używasz Pythona, użyj fsum. W przeciwnym razie spróbuj zaimplementować algorytm sumowania Kahana .
[1]: C i C ++ normy nie określają reprezentację float, doublei long double. Możliwe jest, że wszystkie trzy zostaną zaimplementowane jako podwójna precyzja IEEE. Niemniej jednak dla większości architektur (gcc, MSVC; x86, x64, ARM) float jest rzeczywiście liczbą zmiennoprzecinkową pojedynczej precyzji IEEE (binary32) i double jest liczbą zmiennoprzecinkową podwójnej precyzji IEEE (binary64).