我已经阅读了float似乎double之间的区别。然而,在大多数情况下,float似乎double是可以互换的,即使用其中一种似乎不会影响结果。真的是这样吗?浮点数和双精度数何时可以互换?它们之间有什么区别?
float
double
巨大的差异。
顾名思义, adouble的精度是[1]的 2 倍。一般来说,a有 15 位精度,而有 7 位。floatdouble``float
double``float
以下是位数的计算方式:
double有 52 个尾数位 + 1 个隐藏位:log(2 53 )梅log(10) = 15.95 位 float有 23 个尾数位 + 1 个隐藏位:log(2 24 )梅log(10) = 7.22 位
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,但 double 约为1.7e308,因此使用float可以比简单的计算更容易达到“无穷大”(即特殊的浮点数)double,例如计算 60 的阶乘。
3e38
1.7e308
在测试过程中,可能有几个测试用例包含这些巨大的数字,如果您使用浮点数,可能会导致您的程序失败。
当然,有时,甚至double不够准确,因此我们有时有long double[1](上面的示例在 Mac 上给出 9.000000000000000066),但所有浮点类型都会 出现舍入误差 ,所以如果精度非常重要(例如金钱处理)你应该使用int或分数类。
long double
int
此外,不要使用+=对大量浮点数求和,因为错误会迅速累积。如果您使用的是 Python,请使用fsum. 否则,尝试实现Kahan 求和算法。
+=
fsum
[1]:C 和 C++ 标准没有指定 和的float表示。有可能所有三个都实现为 IEEE 双精度。尽管如此,对于大多数架构(gcc、MSVC;x86、x64、ARM) 来说 确实是一个 IEEE 单精度浮点数(binary32),并且 是 一个 IEEE 双精度浮点数(binary64)。double``long double``float double
double``long double``float