看看这段代码:
#include <cmath>
#include <iostream>
using namespace std;
class Sphere
{
double r;
public:
double V() const { return (4/3) * 3.14 * pow(r,3); }
bool equal(const Sphere& s) const
{
cout << V() << " == " << s.V() << " : " << ( V() == s.V() );
return ( V() == s.V() );
}
explicit Sphere(double rr = 1): r(rr){}
};
main()
{
Sphere s(3);
s.equal(s);
}
输出为84.78 == 84.78 : 0
,这意味着相同的方法每次都不会返回相同的值,即使所有参数都是静态的?
但是如果我在3.0
方法定义中写3.14
而不是V()
,就像这样:
double V() const { return (4/3) * 3.0 * pow(r,3); }
然后,输出为:84.78 == 84.78 : 1
这里发生了什么?我需要这个方法,对于我的程序,它将比较两个对象的体积,但这是不可能的?我把头撞了很长时间才弄明白问题的原因是什么,幸运的是我找到了它,但现在我不明白为什么?它与编译器(GCC)有关,还是我在这里缺少一些重要的东西?
答案 0 :(得分:23)
使用==
运算符比较浮点值非常容易出错; 应该相等的两个值可能不是由于算术舍入错误。比较这些的常用方法是使用epsilon:
bool double_equals(double a, double b, double epsilon = 0.001)
{
return std::abs(a - b) < epsilon;
}
答案 1 :(得分:4)
浮点比较存在两个问题:
(1)浮点运算通常至少涉及很难预测的微小舍入误差。因此,两个浮点运算应该在数学上给出相同的结果(如4.7 *(1.0 / 3.14)与4.7 / 3.14)可能会给出不同的结果。
(2)允许编译器进行浮点运算,有时精度高于必要值。它也允许使用其他时间所需的精度完成相同的浮点运算。因此,完全相同的操作可能会产生稍微不同的结果,这是您在此处看到的。
为了解决OP的问题,这看起来像是由(2)引起的。我试图找出是否有任何编译器选项可以阻止编译器使用比所需更高的精度。