如何确定一个double的最小显着变化

我有问题来确定给定双变量v的最小值eps

v+eps != v

请注意,这不是典型的问题表单任务,因为eps取决于任意数字v

这不应该通过在for循环中寻找这个值来完成。 有没有快速的方法来做到这一点,例如通过位移? 独立于编译器,优化标志,平台...

感谢您的回答


C99功能nextafter是你需要的。 或者,使用Boost.Math的nextafter 。 这是由定义定义的实现(它依赖于内存中的double的内部表示)。

要比较撰写本文时答案中提供的所有方法,请参阅现场演示以了解其他解决方案如何失败。


作为参考,如果你想在我们自己的系统上运行它,这里是测试代码:

#include <cmath>
#include <cfloat>
#include <limits>
#include <iostream>
using std::cout;
#include <iomanip>
using std::setprecision;

#include <boost/math/special_functions/next.hpp>

double
epsFor( double x )
{
  union
  {
    double d;
    unsigned long long i;
  } tmp;
  tmp.d = x;
  ++ tmp.i;
  return tmp.d - x;
}

void test(double d)
{
  double d1 = std::nextafter(d,DBL_MAX);
  double d2 = d+std::numeric_limits<double>::epsilon() * d;
  double d3 = d+epsFor(d);
  double d4 = boost::math::nextafter(d, DBL_MAX);
  cout << setprecision(40)
       << "For value of d = " << d << 'n'
       << " std::nextafter: " << d1 << 'n'
       << " Boost solution: " << d4 << 'n'
       << " undefined beh.: " << d3 << 'n'
       << " numeric_limits: " << d2 << 'n';
}

int main()
{
  test(0.1);
  test(986546357654.354687);
}

我会使用类型双击:

double
epsFor( double x )
{
    union
    {
        double d;
        unsigned long long i;
    } tmp;
    tmp.d = x;
    ++ tmp.i;
    double results = tmp.d - x;
    return results;
}

(形式上,这是未定义的行为,但在实践中,我不知道它会失败的现代编译器。)

编辑:

请注意,C ++允许在中间表达式中过度精确; 由于我们在这里关注的是确切的结果,因此如果您直接在表达式中使用原始发布的函数,则可能会给出错误的结果,而不是将其分配给double 。 我在函数中添加了一个赋值来避免这种情况,但请注意,至少在默认情况下,很多编译器在这方面不符合标准。 (g ++是一个很好的例子,你需要一个特殊的选项来保持一致的行为,至少在开启优化时如果你使用g ++,如果你想得到正确的结果,你必须指定-ffloat-store选项。)


eps = std::numeric_limits<double>::epsilon() * v;
链接地址: http://www.djcxy.com/p/74889.html

上一篇: How to determine the minimal noticable change of a double

下一篇: servlet on Tomcat 7 vs Spray