c ++两个double值的比较不能正常工作

c++ comparison of two double values not working properly

本问题已经有最佳答案,请猛点这里访问。

查看此代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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,这意味着即使所有参数都是静态的,相同的方法也不会每次返回相同的值?

但如果我在V()方法定义中写3.0而不是3.14的话,如下:

1
double V() const { return (4/3) * 3.0 * pow(r,3); }

然后,输出为:84.78 == 84.78 : 1

这是怎么回事?我需要这个方法,用于我的程序,它将比较两个对象的体积,但这是不可能的?我撞了好长时间才弄清楚问题的原因,幸运的是我找到了,但现在我不明白为什么了??它与编译器(GCC)有什么关系,还是我在这里遗漏了一些重要的东西?


使用==运算符比较浮点值非常容易出错;两个应该相等的值可能不是由于算术舍入错误造成的。比较这些的常用方法是使用epsilon:

1
2
3
4
bool double_equals(double a, double b, double epsilon = 0.001)
{
    return std::abs(a - b) < epsilon;
}


浮点比较有两个问题:

(1)浮点运算通常至少涉及很难预测的微小舍入误差。因此,在数学上给出相同结果的两个浮点运算(如4.7*(1.0/3.14)与4.7/3.14)可能给出不同的结果。

(2)编译器可以执行浮点运算,有时精度比需要的要高。它还允许执行完全相同的浮点运算,而只使用其他时间所需的精度。因此,相同的操作可能会产生稍微不同的结果,这就是您在这里看到的。

为了解决OP的问题,这看起来是由(2)引起的。我将尝试找出是否有任何编译器选项可以阻止编译器使用比需要更高的精度。