Реализовать функцию Matlab’s eps (x) в переполнении стека

Я пытаюсь реализовать Matlab’s 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.1035e-05, как в Matlab.

Какие-нибудь мысли?

6

Решение

Включают <cmath> и позвонить std::nextafterи ваш код будет работать при условии, что у вас есть компилятор C ++ 11.

В том числе <math.h> и звонит ::nextafter вызывает C-версию функции. C реализация nextafter очевидно, не поддерживает никаких перегрузок, поэтому C обеспечивает nextafterf для получения результата с одинарной точностью, а также nextafterl для четверной точности. (Просто вызов двойной точности nextafter с float не удается, потому что аргумент преобразуется в double.) Если у вас нет компилятора C ++ 11, вы можете исправить свой код, вызвав ::nextafterf,

6

Другие решения

Используйте библиотеки. Matlab-х eps Функция на других языках называется ULP, за единицу на последнем месте. Согласно статье в Википедии ULP, следующая функция из повысить C ++ библиотека может использоваться для вычисления расстояния с плавающей точкой между двумя двойными a а также b:

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

Документация для float_distance является Вот.

1

По вопросам рекламы [email protected]