Implement matlab eps (x) function in C ++

I am trying to implement the matlab eps(x) function in C ++

For example, in Matlab:

 >> eps(587.3888) ans = 1.1369e-13 >> eps(single(587.3888)) ans = 6.1035e-05 

However, when I try to do this in C ++, I cannot get the correct single-precision answer.

 #include <limits> #include <iostream> #include <math.h> #define DEBUG(x) do { std::cerr << x << std::endl; } while (0) #define DEBUG2(x) do { std::cerr << #x << ": " << x << std::endl; } while (0) int main() { float epsf = std::numeric_limits<float>::epsilon(); DEBUG2(epsf); double epsd = std::numeric_limits<double>::epsilon(); DEBUG2(epsd); float espxf = nextafter(float(587.3888), epsf) - float(587.3888); double espxd = nextafter(double(587.3888), epsd) - double(587.3888); DEBUG2(espxf); DEBUG2(espxd); } 

Running the program I get the following output:

 $ ./a.out epsf: 1.19209e-07 epsd: 2.22045e-16 espxf: -1.13687e-13 espxd: -1.13687e-13 

It seems that for some reason, although the eps values ​​for single and double precision are correct, exiting using the nextafter function nextafter outputs the double precision value. My value for epsxf should be 6.1035e-05, as in Matlab.

Any thoughts?

+6
source share
2 answers

Include <cmath> and call std::nextafter , and your code will work if you have a C ++ 11 compiler.

Including <math.h> and calling ::nextafter calls the C version of the function. The C implementation of nextafter obviously does not support overloads, so C provides nextafterf for the result with one precision, as well as nextafterl for quad-precision. (Just calling double-precision nextafter with float fails because the argument is converted to double .) If you don't have a C ++ 11 compiler, you can fix your code by calling ::nextafterf .

+6
source

Use libraries. The Matlab eps function in other languages ​​is called ULP, for the unit in last place. According to the Wikipedia article on ULP , the following function from boost C ++ library can be used to calculate the floating point distance between two doubles a and b :

 boost::math::float_distance(a, b) 

The documentation for float_distance here .

+1
source

Source: https://habr.com/ru/post/958707/


All Articles