user1285419
user1285419

Reputation: 2225

about float number comparision in C++

I have a loop to loop a floating number between given min and max range as follow

#include <iostream>
using namespace std;

void main(void)
{
  for (double x=0.012; x<=0.013; x+=0.001) 
  {
    cout << x << endl;
  }
}

It is pretty simple code but as I know in computer language, we need to compare two floating numbers with EPS considered. Hence, above code doesn't work (we expect it to loop two times from 0.012 to 0.013 but it only loop once). So I manually add an EPS to the upper limit.

#include <iostream>
using namespace std;
#define EPS 0.0000001

void main(void)
{
  for (double x=0.012; x<=0.013+EPS; x+=0.001) 
  {
    cout << x << endl;
  }
}

and it works now. But it looks ugly to do that manually since EPS should really depends on machine. I am porting my code from matlab to C++ and I don't have problem in matlab since there is eps command. But is there anything like that in C/C++?

Upvotes: 0

Views: 139

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 222724

Fudging the comparison is the wrong technique to use. Even if you get the comparison “right”, a floating-point loop counter will accumulate error from iteration to iteration.

You can eliminate accumulation of error by using exact arithmetic for the loop counter. It may still have floating-point type, but you use exactly representable values, such as:

for (double i = 12; i <= 13; ++i)

Then, inside the loop, you scale the counter as desired:

for (double i = 12; i <= 13; ++i)
{
    double x = i / 1000.;
     …
}

Obviously, there is not much error accumulating in a loop with two iterations. However, I expect your values are just one example, and there may be longer loops in practice. With this technique, the only error in x is in the scaling operation, so just one error in each iteration instead of one per iteration.

Note that dividing by 1000 is more accurate than scaling by .001. Division by 1000 has only one error (in the division). However, since .001 is not exactly representable in binary floating point, multiplying by it has two errors (in the conversion of .001 to floating point and in the multiplication). On the other hand, division is typically a very slow operation, so you might choose the multiplication.

Finally, although this technique guarantees the desired number of iterations, the scaled value might be slight outside the ideal target interval in the first or the last iteration, due to the rounding error in the scaling. If this matters to your application, you must adjust the value in these iterations.

Upvotes: 3

Related Questions