Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ comparison of two double values not working properly [duplicate]

Look at this code:

#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);
}

The output is 84.78 == 84.78 : 0 which means the same method doesn't return the same value every time, even though all parameters are static?

But if I write 3.0 instead of 3.14 in the V() method definition, like this:

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

Then, the output is: 84.78 == 84.78 : 1

What is going on here? I need this method, for my program, which will compare volumes of two objects, but it is impossible? I banged my head for so long to figure out what is the cause of the problem and luckily I found it, but now I don't understand why?? Does it have something to do with the compiler (GCC) or am I missing something important here?

like image 825
tuks Avatar asked Sep 24 '13 01:09

tuks


People also ask

Can we compare double in C?

To compare two floating point or double values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Can you use == for double?

Double equals ( == ) will perform a type conversion when comparing two things, and will handle NaN , -0 , and +0 specially to conform to IEEE 754 (so NaN != NaN , and -0 == +0 );

Can we compare double with float?

Correct way of comparing double and float In order to compare double and float, check the difference of two to be greater than or less than a particular margin.

Can double and float compare in C?

The output of above program is "4 8 4" on a typical C compiler. It actually prints size of float, size of double and size of float. The values used in an expression are considered as double (double precision floating point format) unless a 'f' is specified at the end.


2 Answers

Comparing floating point values using the == operator is very error prone; two values that should be equal may not be due to arithmetic rounding errors. The common way to compare these is to use an epsilon:

bool double_equals(double a, double b, double epsilon = 0.001)
{
    return std::abs(a - b) < epsilon;
}
like image 170
nijansen Avatar answered Sep 21 '22 16:09

nijansen


There are two problems with floating point comparisons:

(1) Floating point operations usually involve at least tiny rounding errors which are hard to predict. Therefore two floating point operations that should mathematically give the same result (like 4.7 * (1.0 / 3.14) vs. 4.7 / 3.14) may give different results.

(2) The compiler is allowed to do floating point operations sometimes with higher precision than necessary. It is also allowed to do the exact same floating point operations with just the precision that was necessary at other times. Therefore the exact same operation may produce slightly different results, which is what you see here.

To solve the OP's problem, this looks like it is caused by (2). I'd try to find if there are any compiler options that can prevent the compiler from using higher precision than needed.

like image 33
gnasher729 Avatar answered Sep 17 '22 16:09

gnasher729