Огромная разница.
Как следует из названия, a doubleимеет 2-кратную точность [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
Кроме того, максимальное значение с плавающей точкой составляет около 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).