Physics和std :: numeric_limits <double> :: epsilon()......我们何时以及为什么需要它?

时间:2017-03-15 03:04:44

标签: c++ floating-point

我只是为一个相当简单的物理模拟程序编写了一些代码,用户可以改变重力加速度,我想将最小重力值限制为某个值(以防止0和负重力)。

我最终得到了类似的东西:

if(g_accel > 0.1) {
    g_accel -= 0.1;
}

在程序开始时将g_accel设置为1.0。但是它仍然允许用户低于0.1到1.38778e-016之类的值。我对这个问题的解决方案是检查:

if(g_accel > 0.1+std::numeric_limits<double>::epsilon()) {
    g_accel -= 0.1;
}

除了使用魔法常量之外,我的问题是我不知道为什么这是必要的,而且,我并不真正理解为什么epsilon()有用或者如何/何时使用它。

我刚才看到一些看起来像这样的代码:

inline void Vector2D::Normalize()
{ 
  double vector_length = this->Length();

  if (vector_length > std::numeric_limits<double>::epsilon())
  {
    this->x /= vector_length;
    this->y /= vector_length;
  }
}

使用std :: numeric_limits :: epsilon()进行了什么?

1 个答案:

答案 0 :(得分:2)

std::numeric_limits<T>::epsilon上的infostd::numeric_limits<T>::epsilon()返回1 + std::numeric_limits<T>:epsilon()不等于1的最小此类T.此值仅在std::numeric_limits<T>::is_integer()时有用返回false。该值的名称是机器epsilon。

因为浮点数的表示在可表示的数字之间产生cppreference page,因为数字在数字线上离数字越来越远,因此epsilon()的返回值需要缩放才能与结果。 Christer Ericson的实时碰撞检测描述了缩放背后的一些算法。他在书中建议的建议是,执行浮点等式检查时应该使用的epsilon值应该是机器epsilon的平方根。

Bruce Dawson的博客系列,我在上面链接,是学习浮点运算复杂性的重要资源。如果您想继续实施物理模拟,我强烈建议您阅读本系列中的所有帖子。