用C ++实现Matlab的eps(x)函数

时间:2013-11-23 23:09:13

标签: c++ matlab epsilon

我正在尝试在C ++中实现Matlab的eps(x)函数

例如,在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中一样。

有什么想法吗?

2 个答案:

答案 0 :(得分:6)

包含<cmath>并致电std::nextafter,只要您拥有C ++ 11编译器,您的代码就可以使用。

包括<math.h>和调用::nextafter会调用函数的C版本。 nextafter的C实现显然不支持重载,因此C为单精度结果提供nextafterf,为四精度提供nextafterl。 (简单地用nextafter调用双精度float失败,因为参数转换为double。)如果你没有C ++ 11编译器,你可以修改你的代码调用::nextafterf

答案 1 :(得分:1)

使用库。 Matlab在其他语言中的eps函数称为ULP,在最后一位用于单位。根据维基百科关于ULP的文章,boost C++ library中的以下函数可用于计算两个双精度ab之间的浮点距离:

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

float_distance的文档是here