Величезна різниця.
Як випливає з назви, a double
має вдвічі більшу точність [1] . Загалом a має 15 десяткових цифр точності, тоді як має 7.float
double
float
Ось як обчислюється кількість цифр:
double
має 52 біти мантіси + 1 прихований біт: log (2 53 ) ÷ log (10) = 15,95 цифр
float
має 23 біти мантіси + 1 прихований біт: log (2 24 ) ÷ log (10) = 7,22 цифри
Ця втрата точності може призвести до накопичення більших помилок укорочення при повторних обчисленнях, наприклад
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
поки
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Крім того, максимальне значення float становить приблизно 3e38
, але подвійне - приблизно 1.7e308
, тому використання float
може вражати "нескінченність" (тобто спеціальне число з плаваючою комою) набагато простіше, ніж double
для чогось простого, наприклад, обчислення фактора 60.
Під час тестування, можливо, кілька тестових випадків містять ці величезні числа, що може спричинити збій ваших програм, якщо ви використовуєте плавці.
Звичайно, іноді навіть double
не досить точно, тому ми інколи long double
[1] (вищенаведений приклад дає 9.000000000000000066 на Mac), але всі типи з плаваючою комою страждають від помилок округлення , тому якщо точність дуже важлива (наприклад, гроші обробка) ви повинні використовувати int
або клас дробів.
Крім того, не використовуйте +=
для підсумовування безлічі цифр з плаваючою комою, оскільки помилки накопичуються швидко. Якщо ви використовуєте Python, використовуйте fsum
. В іншому випадку спробуйте реалізувати алгоритм підсумовування Кахана .
[1]: З і С ++ стандарти не визначають відображення float
, double
і long double
. Цілком можливо, що всі три реалізовані як подвійна точність IEEE. Проте, для більшості архітектур (GCC, MSVC; x86, x64, ARM) float
є дійсно IEEE одинарної точності з плаваючою комою (binary32), і double
це IEEE подвійної точності з плаваючою комою (binary64).