7

eps我有问题要确定给定双变量的最小值,v这样

v+eps != v

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

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

感谢您的回答

4

3 回答 3

3

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);
}
于 2013-10-10T09:53:24.773 回答
1

我会使用类型双关语:

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如果你想要正确的结果,你必须指定选项。)

于 2013-10-10T09:36:48.520 回答
0
eps = std::numeric_limits<double>::epsilon() * v;
于 2013-10-10T09:25:52.393 回答