Огромная разница.
Как видно из названия, double
имеет в 2 раза большую точность, чем float
[1] . В общем случае double
имеет 15 десятичных цифр точности, а float
имеет 7.
Вот как рассчитывается количество цифр:
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
Кроме того, максимальное значение с плавающей точкой составляет около 3e38
, а double - около 1.7e308
, поэтому использование float
может достичь «бесконечности» (то есть специального числа с плавающей запятой) гораздо легче, чем double
для чего-то простого, например вычисление факториала 60.
Во время тестирования, возможно, несколько тестовых примеров содержат эти огромные числа, которые могут привести к сбою ваших программ, если вы используете float.
Конечно, иногда даже double
не достаточно точен, поэтому иногда у нас есть long double
[1] (в приведенном выше примере для Mac используется 9.000000000000000066), но страдают все типы с плавающей запятой из ошибок округления , поэтому, если точность очень важна (например, обработка денег), вы должны использовать int
или класс дроби.
Кроме того, не используйте +=
для суммирования большого числа чисел с плавающей запятой, поскольку ошибки быстро накапливаются. Если вы используете Python, используйте fsum
. В противном случае попробуйте реализовать алгоритм суммирования Кахана .
[1]: стандарты C и C ++ не определяют представление float
, double
и long double
. Вполне возможно, что все три реализованы как IEEE двойной точности. Тем не менее, для большинства архитектур (gcc, MSVC; x86, x64, ARM) float
- это действительно число с плавающей запятой IEEE с одинарной точностью (binary32), а double
- число с плавающей точкой двойной точности IEEE (binary64).