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?
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.
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();
}
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;
}
Related
I'm coding a Polynom class in c++. In the following link, it is explained how to return several values using tuple : Returning multiple values from a C++ function
So I tried to code as indicated to return the quotient and the remainder of the polynomial division but it does not work.
Here is my division method :
tuple<Polynome, Polynome> division(Polynome& D)
{
Polynome Q;
Polynome R(*this);
Polynome nul;
int delta(degre() - D.degre());
float a;
while (delta >= 0 && R != nul)
{
a = R.top() / D.top();
Polynome nouveauPoly(a, delta);
Q = Q + nouveauPoly;
R = R - nouveauPoly * D;
delta = R.degre() - D.degre();
}
return {Q, R};
}
Then, when I do as indicated in the link above and begin to code my own operator :
Polynome operator/(Polynome& D)
{
auto [Q, R] = division(D);
}
I get an error telling me Q should be constant value. I don't understand why Q should be so, and where the error come from, especially regarding that this code comes from a top answer in stackoverflow. I tried to first declare the polynomes Q and R but it did not change anything.
Ultimately I found a way to achieve what I wanted using tuples, but I'm still wanting to know exactly why the indicated answer did not work for me.
Thank you very much
It might be that Structured Binding does not work with your compiler version (or the C++ version option). That requires C++17.
If you can't go for C++17, you might want to try out older ways to do this:
Instead of
auto [Q, R] = division(D);
use
Polynome Q, R;
std::tie(Q, R) = division(D);
(This requires #include <tuple>, but I assume that is included already anyway.)
I need to write a float comparison function (equal/not equal) but I have to use C++98 and boost libraries at most. I know that float comparison should include epsilon but I don't know how to write such code without using C++11.
One C++98 example:
#include <cmath>
#include <limits>
#include <iostream>
inline bool equal_with_tolerance(float a, float b, float tolerance = std::numeric_limits<float>::epsilon()) {
return std::abs(a - b) < tolerance;
}
int main() {
float a = 0.1f;
float b = 0.1000001f;
std::cout << (a == b) << '\n'; // Outputs 0.
std::cout << equal_with_tolerance(a, b) << '\n'; // Outputs 1.
}
tolerance depends on your problem domain, using std::numeric_limits<float>::epsilon is rarely adequate, see this for more details.
I know that float comparison should include epsilon but I don't know how
You could use std::numeric_limits<float>::epsilon() to get the "machine" epsilon.
However, floating point equality comparison with tolerance is not quite as simple as directly comparing absolute difference to machine epsilon. Any small epsilon is going to devolve the comparison into an equality comparison for large values, which leaves you with zero error tolerance.
Meaningful tolerant comparison, requires that you know what sort of values you're expecting, their magnitude, their sign, expected error that you wish to tolerate.
This blog explains the problem in intricate detail. It suggests following, which may be reasonable for "generic" comparison
bool AlmostEqualRelativeAndAbs(float A, float B,
float maxDiff, float maxRelDiff = FLT_EPSILON)
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
float diff = fabs(A - B);
if (diff <= maxDiff)
return true;
A = fabs(A);
B = fabs(B);
float largest = (B > A) ? B : A;
if (diff <= largest * maxRelDiff)
return true;
return false;
}
The example is in C, but trivial to translate to C++ idioms. There is also an ULP based function in the article, but its implementation relies on union type punning that is not allowed in C++.
I've written a kd-tree template, it's parameter being a natural number K.
As part of the template, I've written the following function to compute the distance between two points (kd_point is an alias for std::array)
template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
float Sum = 0;
for (unsigned i = 0; i < K; i++)
Sum += (P[i] - Q[i]) * (P[i] - Q[i]);
return Sum;
}
I've turned "Enable C++ Core Check (Release)" on, and it gives me said warning. Is there a right way to write this routine to eliminate the warning?
Since you mention in comments that your kd_point's support range based iteration (so I assume can return iterators), you can re-write the function without the raw loop. Use named algorithms from the standard library instead:
template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
return std::inner_product(
begin(P), end(P), begin(Q), 0.0f, std::plus<float>{},
[](float pi, float qi) {
return (pi - qi)*(pi - qi);
}
);
}
The standard library would be exempt from the warning, of course. If the (in this case) marginal benefit of replacing a raw loop by a named operation doesn't appeal to you, consider that if you ever come back to this code with a C++17 enabled compiler, you'll be able to almost effortlessly parallelize it:
template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
return std::transform_reduce(std::execution::par, // Parallel execution enabled
begin(P), end(P), begin(Q), 0.0f, std::plus<float>{},
[](float pi, float qi) {
return (pi - qi)*(pi - qi);
}
);
}
Answer by StoryTeller is probably the most suitable C++ way to solve this particular task.
I would like to add that in general, if you want to iterate not over one, but over two sequences simultaneously, you can use "secret overload of boost::range::for_each", accepting two ranges:
#include <boost/range/algorithm_ext/for_each.hpp>
template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
float Sum = 0;
boost::range::for_each(P, Q, [&Sum](float p, float q)
{
Sum += (p - q) * (p - q);
});
return Sum;
}
Note that similarly to standard algorithms, this algorithm is header-only and won't bring any library dependency to your code.
As seen in this question, there is a difference between the results MKL gives, between serial and distributed execution. For that reason, I would like to study that error. From my book I have:
|ε_(x_c)| = |x - x_c| <= 1/2 * 10^(-d), where d specifies the decimal digits that are accurate, between the actual number, x and the number the computer has, x_c.
|ρ_(x_c)| = |x - x_c|/|x| <= 5 * 10^(-s) is the absolute relative error, where s specifies the number of significant digits.
So, we can write code like this:
double calc_error(double a,double x)
{
return std::abs(x-a)/std::abs(a);
}
in order to compute the absolute error for example, as seen here.
Are there more types of errors to study, except from the absolute error and the absolute relative error?
Here are some of my data to play with:
serial gives:
-250207683.634793 -1353198687.861288 2816966067.598196 -144344843844.616425 323890119928.788757
distributed gives:
-250207683.634692 -1353198687.861386 2816966067.598891 -144344843844.617096 323890119928.788757
and then I can expand the idea(s) to the actual data and results.
It doesn't get much more complicated than absolute and absolute relative errors. There is another method that compares integer-representations of floating-point formats, the idea being that you want your "tolerance" to adapt with the magnitude of the numbers you are comparing (specifically because there aren't "as many" numbers representable depending on the magnitude).
All in all, I think your question is very similar to floating-point comparison, for which there is this excellent guide, and this more exhaustive but much longer paper.
It might also be worth throwing in these for comparing floating point values:
#include <limits>
#include <cmath>
template <class T>
struct fp_equal_strict
{
inline bool operator() ( const T& a, const T& b )
{
return std::abs(a - b)
<= std::max(
std::numeric_limits<T>::min() * std::min( std::abs(a), std::abs(b) ),
std::numeric_limits<T>::epsilon()
);
}
};
template <class T>
struct fp_equal_loose
{
inline bool operator() ( const T& a, const T& b )
{
return std::abs(a - b)
<= std::max(
std::numeric_limits<T>::min() * std::max( std::abs(a), std::abs(b) ),
std::numeric_limits<T>::epsilon()
);
}
};
template <class T>
struct fp_greater
{
inline bool operator() ( const T& a, const T& b )
{
return (a - b) >= std::numeric_limits<T>::min() * std::max( std::abs(a), std::abs(b) );
}
};
template <class T>
struct fp_lesser
{
inline bool operator() ( const T& a, const T& b )
{
return (b - a) >= std::numeric_limits<T>::min() * std::max( std::abs(a), std::abs(b) );
}
};
I would mention that it is also possible to perform an ULPs (Units in the Last Place) comparison, which shows how far away two floating point numbers are in the binary representation. This is a nice indication of "closeness" since if two numbers are for example one ULP apart it means that there is no floating point number between them, so they are as close as possible in the binary representation without acutally being equal.
This method is descrbied here which is a more recent version than the article linked from the accepted answer by the same author. Sample code is also provided.
As an aside, but related to the context of your work (comparing sequential vs parallel floating point computations) it is important to note that floating point operations are not associative which means parallel implementations may not in general give the same result as sequential implementations. Even changing the compiler and optimisation options can actually lead to different results (e.g. GCC vs ICC, -O0 vs -O3).
An example algorithm on how to reduce the error computation for performing summation of floating point numbers can be found here and a comprehensive document by the author of that algorithm can be found here.
For example, I have a simple macro
#define MIN(a, b) (a) < (b) ? (a) : (b)
and I want to use
MIN(pow(2, 3) , 10);
The internal common gives trouble. I can do as following
int a = pow(2, 3);
MIN(a, 10);
I am looking for a better way that is more readable by like keeping pow(2, 3) in the macro? Is it possible? Thanks!
You can use std::min instead:
#include <algorithm>
//...
double x = std::min(pow(2, 3) , 10);
Generally, you should prefer an inline function over a macro. If the purpose of the macro is to allow it to work for a variety of types, you can use a template.
template <typename T>
inline T SomeFunction (T x, T y) {
T result;
//...do something with x and y and assign to result
return result;
}