7
\$\begingroup\$

Is this the best way to check if two floating point numbers are equal, or close to being equal?

template <class T>
bool IsEqual(T rhs, T lhs)
{
    T diff = std::abs(lhs - rhs);

    T epsilon = std::numeric_limits<T>::epsilon( ) * std::max(std::abs(rhs), std::abs(lhs));

    return diff <= epsilon ;
}
\$\endgroup\$
8
  • 1
    \$\begingroup\$ So I should consider: 100000000000000000 and 100000000000000020 to be the same number? \$\endgroup\$ Commented Oct 26, 2012 at 14:23
  • \$\begingroup\$ PS. Typo inside std::max() you have two rhs. \$\endgroup\$ Commented Oct 26, 2012 at 14:24
  • 1
    \$\begingroup\$ @LokiAstari With floating point numbers, they are not accurate and the farther away you get from 1 the less accurate you get. Therefore, I'm trying to check if they are equal with some reason. To answer your question, yes those two values should be equal. But at the same time, I don't want 1 == 20 \$\endgroup\$
    – Caesar
    Commented Oct 26, 2012 at 14:42
  • 1
    \$\begingroup\$ Correct. And if that is what you need fine. But it is not what most people are going to need. I would use @William Morris solution as this would be more normal usage as i do want to distinguish larger numbers. \$\endgroup\$ Commented Oct 26, 2012 at 15:40
  • \$\begingroup\$ @LokiAstari The thing is that you can't guarantee that your large numbers are stored accurately. \$\endgroup\$
    – Caesar
    Commented Oct 26, 2012 at 15:49

2 Answers 2

3
+50
\$\begingroup\$

No, not really. You want a third parameter that gives an acceptable difference -- this can be number of decimals, percent of value, or a fixed value, but it needs to be coming from outside to really be useful.

A function that does it with a constant diff, might be useful in some limited circumstances, but not generally.

\$\endgroup\$
4
\$\begingroup\$

Seems unlikely. epsilon from std::numeric_limits is the smallest increment representable by the type (around the value 1).

You want to check for something "close to" equal, but you don't say what close to means for you. Assuming it to be a few multiples of epsilon, the following check would seem reasonable:

const int FEW = 10;
T diff = std::abs(lhs - rhs);
T epsilon = std::numeric_limits<T>::epsilon();

return diff < (epsilon * FEW);
\$\endgroup\$
1
  • 1
    \$\begingroup\$ From my understanding, floating point numbers get less and less accurate the further away you get from 1. While you code is fine, it is only gone work for a small lower range of floating point numbers. \$\endgroup\$
    – Caesar
    Commented Oct 26, 2012 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.