C++ 物理和标准::数值限制<;双重>;::epsilon()…何时以及为什么我们需要它?

C++ 物理和标准::数值限制<;双重>;::epsilon()…何时以及为什么我们需要它?,c++,floating-point,C++,Floating Point,我只是在为一个相当简单的物理模拟程序编写一些代码,用户可以改变重力加速度,我想将最小重力值限制在某个值(以防止0和负重力) 我的结局是这样的: if(g_accel > 0.1) { g_accel -= 0.1; } inline void Vector2D::Normalize() { double vector_length = this->Length(); if (vector_length > std::numeric_limits<do

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

我的结局是这样的:

if(g_accel > 0.1) {
    g_accel -= 0.1;
}
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;
  }
}
其中,g_accel在程序开始时设置为1.0。但是,它仍然允许用户将0.1降至1.38778e-016之类的值。我的解决方案是检查:

if(g_accel > 0.1+std::numeric_limits<double>::epsilon()) {
    g_accel -= 0.1;
}
if(g\u accel>0.1+std::numeric\u limits::epsilon()){
g_加速度-=0.1;
}
除了使用魔法常数,我的问题是我不知道为什么这是必要的,而且,我真的不明白为什么epsilon()有用,或者如何/何时使用它

我刚才还在看一些代码,看起来像这样:

if(g_accel > 0.1) {
    g_accel -= 0.1;
}
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;
  }
}
inline void Vector2D::Normalize()
{ 
双向量长度=此->长度();
如果(向量长度>标准::数值限制::ε()
{
这->x/=向量长度;
这->y/=向量长度;
}
}
std::numeric_limits::epsilon()怎么了?

std::numeric_limits::epsilon
上,
std::numeric_limits::epsilon()
返回
1+std::numeric_limits:epsilon()
不等于1的最小T。只有当
std::numeric\u limits::is\u integer()
返回false时,此值才有用。该值的名称为机器ε

由于浮点数的表示会导致可表示数字之间的差异,因为数字在数字行上离0越远,
epsilon()
的返回值需要缩放才能与结果一起工作。克里斯特·埃里克森(Christer Ericson)的实时碰撞检测描述了缩放背后的一些数学原理。他在书中提出的建议是,执行浮点相等性检查时应使用的ε值应为机器ε的平方根


布鲁斯·道森(Bruce Dawson)的博客系列,我在上面链接了它,它是学习浮点运算复杂性的一个很好的资源。如果您想继续实现物理模拟,我强烈建议您阅读本系列的所有文章。

对于浮点类型,您可以尝试在有限的位中存储无限个小数。这是不可能的,因此我们得到舍入误差,其中一个值应该是
1.0
,而可能是
0.999998674
或其他值。另请参见,例如,和应有帮助。