发布日期:2018-03-26
float和double的区别+ 查看更多
float和double的区别
+ 查看更多
发布日期:2018-02-26 15:54
分类:CPlusPlus
浏览次数:252
我已经阅读关于double和float之间的差异,但他们在大多数情况下给出的结果应该是相同的,对吧?
我正在解决一个编程竞赛的问题,里面有不是很大的浮点数的计算,所以我决定使用float而不是double,我检查了,并且得到了正确的结果。但是当我提交解决方案后,它说只有十分之一的测试是正确的。我一次又一次检查,直到我发现使用float和使用double是不一样的。我使用double计算并输出,程序给了同样的结果,但这次它正确的通过了所有10个测试。
我重复操作,同样的输出,同样的结果,但使用float无法通过测试,只有使用double能够通过测试。值也不是很大,使用float和double进行相同的测试,程序给出了相同的结果,但在线判断只接受double提供的解决方案。
为什么?他们有什么不同?
回答
差异巨大。
顾名思义,double的精度为float [1] 的2倍。一般来说,double有15个十进制数字的精度,而float只有7个。
以下是计算位数的方法:
double有52个尾数位+1个隐藏位:log(253)÷log(10)= 15.95位 float有23个尾数位+1个隐藏位:log(224)÷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); // 输出 9.000023而
double a = 1.0 / 81; double b = 0; for (int i = 0; i < 729; ++ i) b += a; printf("%.15g\n", b); // 输出 8.99999999999996另外,float的最大值约为3e38,但double的最大值约为1.7e308,所以对于一些计算,使用float比使用double更容易溢出。比如:计算60的阶乘。
也许他们的测试用例包含这些巨大的数字,导致您的程序崩溃。
当然,有时甚至连double都不够精确,因此我们有时使用long double [1] (上面的例子在Mac上输出了9.000000000000000066),但是所有浮点类型都有舍入误差,所以如果精度非常重要(比如:货币处理),你应该使用int或分数类。
顺便提一下,不要使用+=来对大量的浮点数求和,因为错误会迅速累积。如果你使用Python,使用fsum命令。否则,尝试实现Kahan求和算法。
[1] :C和C++标准没有指定float,double和long double的表示。可能三个都被实现为IEEE双精度。然而,对于大多数体系结构(gcc,MSVC,x86,x64,ARM)float确实是IEEE单精度浮点数(32位二进制),double是IEEE双精度浮点数(64位二进制)。