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.
- If your numbers have magnitude greater than
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
Regex Match Digits Between Strings
Print a Binary Tree in a Pretty Way
Iterator Invalidation Rules For C++ Containers
Strange Output in Comparison of Float With Float Literal
How to Parse a String to an Int in C++
What Is the Proper Declaration of Main in C++
What Happens If I Define a 0-Size Array in C/C++
What Exactly Is One Definition Rule in C++
When Should I Use the New Keyword in C++
What's the Most Efficient Way to Erase Duplicates and Sort a Vector
How to Find Out If an Item Is Present in a Std::Vector
Which Kind of Pointer Do I Use When
Using Arrays or Std::Vectors in C++, What's the Performance Gap
How to Get the Directory That a Program Is Running From
Using G++ to Compile Multiple .Cpp and .H Files