What Is the Most Effective Way For Float and Double Comparison

Modern practice to compare double/float for equality in modern C++ [duplicate]

Is this code with modern C++11/14/17/21 is still the way we should compare float and doubles, or now it's ok just to write if (double1 == double2) And compiler will handle the epsilon issue for us?

Both approaches function the same in modern C++ as they did in early C++.

Both approaches are also flawed.

  • Using == assumes that your code has accounted for any floating point rounding errors, and it's very rare/difficult for code to do that.

  • Comparing against epsilon assumes that a reasonable amount of rounding error will be less than the constant epsilon, and that is very likely a wrong assumption!

    • If your numbers have magnitude greater than 2.0, your epsilon trick will be no different from direct comparison, and have the same flaws. Regardless of whether you use < or <=.
    • If your numbers have the same sign and a magnitude smaller than epsilon, your epsilon trick will say they are always equal, even if one is hundreds of times larger than the other. They would both be equal to zero, too.

A wise approach may be to avoid writing code that depends on whether floating point numbers are equal. Instead test if they are relatively close, by some factor.

The code below will test whether two numbers are within about 0.01% of each other. Regardless of their scale.

const auto relative_difference_factor = 0.0001.    // 0.01%
const auto greater_magnitude = std::max(std::abs(double1),std::abs(double2));

if ( std::abs(double1-double2) < relative_difference_factor * greater_magnitude )
std::cout<<"Relatively close";
else
std::cout<<"Not relatively close";

How to correctly and standardly compare floats?

Thanks for your answers, they helped me a lot. I've read these materials:first and second

The answer is to use my own function for relative comparison:

bool areEqualRel(float a, float b, float epsilon) {
return (fabs(a - b) <= epsilon * std::max(fabs(a), fabs(b)));
}

This is the most suitable solution for my needs. However I've wrote some tests and other comparison methods. I hope this will be useful for somebody. areEqualRel passes these tests, others don't.

#include <iostream>
#include <limits>
#include <algorithm>

using std::cout;
using std::max;

bool areEqualAbs(float a, float b, float epsilon) {
return (fabs(a - b) <= epsilon);
}

bool areEqual(float a, float b, float epsilon) {
return (fabs(a - b) <= epsilon * std::max(1.0f, std::max(a, b)));
}

bool areEqualRel(float a, float b, float epsilon) {
return (fabs(a - b) <= epsilon * std::max(fabs(a), fabs(b)));
}

int main(int argc, char *argv[])
{
cout << "minimum: " << FLT_MIN << "\n";
cout << "maximum: " << FLT_MAX << "\n";
cout << "epsilon: " << FLT_EPSILON << "\n";

float a = 0.0000001f;
float b = 0.0000002f;
if (areEqualRel(a, b, FLT_EPSILON)) {
cout << "are equal a: " << a << " b: " << b << "\n";
}
a = 1000001.f;
b = 1000002.f;
if (areEqualRel(a, b, FLT_EPSILON)) {
cout << "are equal a: " << a << " b: " << b << "\n";
}
}

Is to round a correct way for making float-double comparison

Usually, if you really have to compare floating values, you'd specify a tolerance:

bool CompareDoubles1 (double A, double B, double tolerance)
{
return std::abs(A - B) < tolerance;
}

Choosing an appropriate tolerance will depend on the nature of the values and the calculations that produce them.

Rounding is not appropriate: two very close values, which you'd want to compare equal, might round in different directions and appear unequal. For example, when rounding to the nearest integer, 0.3 and 0.4 would compare equal, but 0.499999 and 0.500001 wouldn't.

Is it more efficient to compare float than double?

It is typically either the same or slightly faster to compare a float to a float than a double to a double, but the difference is typically miniscule either way. The bigger performance problem you might be looking at is the conversion from float to double, which can either be free or pretty expensive, depending on where and how it is being done.

Either way, it's really not worth worrying too much about unless you have profiled and found a bottleneck in some huge loop involving this function, in which case you can then test the performance difference yourself and react accordingly.

What is correct way to compare 2 doubles values? [duplicate]

So the question will be is there a generic solution/workaround for this

There will not be a universal solution for finite precision floating point that would apply to all use cases. There cannot be, because the correct threshold is specific to each calculation, and cannot generally be known automatically.

You have to know what you are comparing and what you are expecting from the comparison. Full explanation won't fit in this answer, but you can find most information from this blog: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ (not mine).


There is however a generic solution/workaround that side-steps the issue: Use infinite precision arithmetic. The C++ standard library does not provide an implementation of infinite precision arithmetic.



Related Topics



Leave a reply



Submit