Величезна різниця.
Як випливає з назви, a doubleмає вдвічі більшу точність [1] . Загалом a має 15 десяткових цифр точності, тоді як має 7.floatdoublefloat
Ось як обчислюється кількість цифр:
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).