Home > Software engineering >  When to use std::numeric_limits<double>::espsilon() instead of DBL_EPSILON
When to use std::numeric_limits<double>::espsilon() instead of DBL_EPSILON

Time:11-17

I understood that std::numeric_limits::espsilon() and DBL_EPSILON should deliver the same value but are defined in different headers, limits, and cfloat. Which makes std::numeric_limits::espsilon() a c style way of writing and DBL_EPSILON the c style.

My question is if there is any benefit in using std::numeric_limits::espsilon() over DBL_EPSILON in c project? Aside from a clean c coding style. Or did I understand this completely wrong?

CodePudding user response:

Here on this page https://en.cppreference.com/w/cpp/types/numeric_limits you can find tables of what are the C marco equivalents of the std::numeric_limits.

They are equivalents, so for any pair of std::limits function/constant and C macro you find in the table, they can be interchanged.

The big difference is in generic code:

template <typename T>
void foo() {
     std::cout << std::numeric_limits<T>::epsilon();
}

Doing the same with C macros would require to write much more code. Also any opportunity to not use a macro is a good one.

CodePudding user response:

First of all DBL_EPSILON is a C API so it is a good practice to use C specific API in C code. I know it is more typing, still it is a good practice. In my code when I need epsilon multiple times for single type, I just bind it to some constexpr.

More important thing this is a great tool when you write a template. For example:

template<std::floating_point T>
bool fuzzyCompare(T a, T b)
{
    return std::fabs(a - b) <= 4 * std::max(std::fabs(a), std::fabs(b)) * std::numeric_limits<T>::espsilon();
}

CodePudding user response:

One obvious advantage of using std::numeric_limits<T>::epsilon is generic function. Imagine if you write some function like an almost-equal. This function should accept floating numbers of different precisions, including double, float, long double. Or maybe even integer types as well. To write this with the macro solution, you would have to write an overload for each of the floating point types:

bool almost_equal(float a, float b, int k)
{
    return std::abs(a - b) <= FLT_EPSILON * std::abs(a   b) * k;
}

bool almost_equal(double a, double b, int k)
{
    return std::abs(a - b) <= DBL_EPSILON * std::abs(a   b) * k;
}

...

But with the numeric_limits template, you can simply write a single function for all of them:

template<typename T>
bool almost_equal(T a, T b, int k)
{
    return std::abs(a - b) <= std::numeric_limits<T>::epsilon() * std::abs(a   b) * k;
}
  •  Tags:  
  • c
  • Related