Реализовать функцию eps(x) Matlab в C++
Я пытаюсь реализовать функцию Matlab eps(x)
в C++
Например, в Matlab:
>> eps(587.3888)
ans = 1.1369e-13
>> eps(single(587.3888))
ans = 6.1035e-05
Однако, когда я пытаюсь сделать это в C++, я не могу получить правильный однозначный ответ.
#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);
}
Запустив программу, я получаю следующий результат:
$ ./a.out
epsf: 1.19209e-07
epsd: 2.22045e-16
espxf: -1.13687e-13
espxd: -1.13687e-13
Кажется, что по какой-то причине, даже если значения eps для одиночной и двойной точности верны, выход с помощью функции nextafter
выводит только значение двойной точности. Мое значение для epsxf
должно быть 6.1035 e-05, как в Matlab.
Есть какие-нибудь мысли?
2 ответа:
Включите
<cmath>
и вызовитеstd::nextafter
, и ваш код будет работать, если у вас есть компилятор C++11.Включая
<math.h>
и вызывая::nextafter
вызывает C-версию функции. C-реализацияnextafter
, очевидно, не поддерживает никаких перегрузок, поэтому C предоставляетnextafterf
для результата с одной точностью, а такжеnextafterl
для квадратичной точности. (Простой вызов двойной точностиnextafter
сfloat
терпит неудачу, потому что аргумент преобразуется вdouble
.) Если у вас нет компилятора C++11, вы можете исправить свой код вызывая::nextafterf
.
Используйте библиотеки. Matlab's
eps
функция в других языках называется ULP, для единицы на последнем месте. Согласно статье Википедии на ULP , следующая функция из библиотеки boost C++ может быть использована для вычисления расстояния с плавающей точкой между двумя двойникамиa
иb
:boost::math::float_distance(a, b)
Документация для
float_distance
находитсяздесь .