user2509663
user2509663

Reputation: 179

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

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?

Upvotes: 0

Views: 412

Answers (3)

Ranoiaetep
Ranoiaetep

Reputation: 6647

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;
}

Upvotes: 0

Marek R
Marek R

Reputation: 38062

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();
}

Upvotes: 0

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122830

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.

Upvotes: 2

Related Questions