Advertisement

C++ comparing 2 floats

Started by January 20, 2018 11:39 AM
5 comments, last by swiftcoder 6 years, 10 months ago

hi all, I'm testing with floats for the first time and have discovered that you can't compare 2 floats due to rounding errors. I've read online that you must use an epsilon and test for less than, however I don't seem to be able to get it working with the below code. - when running the code below it it is looping through 6 floats testing for equality with f entered by the player, but even if I put something totally different from the options, the message "not a valid position" is never executed

 


void locks::try_lock()
{
    print("\nEnter lock position: ");
    float f; cin >> f;
    int fexists = 1;
    float epsilon = 0.0000001; // Not sure what the best value to put here is?
    for (float &a : this->answers)
    {
        if ((a - f) < epsilon)
        {
        fexists = 0;
        }
    }
    if (fexists == 1)
    {
        cout << endl << f << " is not a valid position\n\n";
        Sleep(2000);
        return;
    }
}

 

At least: You need to use the absolute value of the difference, something like


  if (fabs(a-f) < epsilon)

or else you check whether a is greater than f and is close to f or a is lesser than f regardless how close. 

Advertisement

Is your logic backwards?

You have a "boolean" you set to "true" (in C++ we actually have types and constants for that, using them can make it easier to reason about logic).  You iterate through a list of values comparing them to your input value, and if at least one of the values matches, you set the "boolean" to "false" to indicate f is in the list.  If that "boolean" named fexists is still "true" by the end of the loop, it indicates f does not exist.

I  realize it doesn't answer you question, but...

Stephen M. Webb
Professional Free Software Developer

thanks haegarr, that fixed it.

 

and thanks Bregma, my logic was backwards, when writing that code I was wrongly thinking that 'return 0' indicates a 'true' and successful end to the program, when it is infact true values that indicate failure

Your epsilon value is really too small to do meaningful general float comparisons.  floats are only 32bits, so there are not enough bits for that precision especially with larger float numbers.

A value of 0.0001 would work better but be WARNED! there are many situations where this is still a problem and in general you don't want a fixed epsilon value as larger float numbers have less precision.

Also you need to consider things like


float EPLISON = 0.0001f;

float a = 123.00015f;
float b = 123.0001f;

if (fabs(a - b) < EPLISON)
{
  std::cout << "Same" << std::endl;
}

float d = a * 100.0f;
float e = b * 100.0f;


if (fabs(d - e) < EPLISON)
{
  std::cout << "Same" << std::endl;
}

 

In this case a ==b but c!=d  although c = 100*a and d = 100*b

See here about float comparison problems

 
 
 

 

3 hours ago, ICanC said:

I was wrongly thinking that 'return 0' indicates a 'true' and successful end to the program, when it is infact true values that indicate failure

When returning from main(), I recommend using EXIT_SUCCESS/EXIT_FAILURE. These are unambiguous, and will map to whatever your OS considers to be the correct exit values (typically POSIX's zero==success).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement