将浮点数与零进行比较的标准方法是什么?

时间:2013-11-03 16:06:59

标签: c++ floating-point

可能问题是:将浮点数与零进行比较的标准方法是什么?

据我所知,直接比较:

if ( x == 0 ) { 
  // x is zero?
} else {
  // x is not zero??

可能会因浮点变量而失败。

我以前用过

float x = ...
...
if ( std::abs(x) <= 1e-7f ) { 
  // x is zero, do the job1
} else {
 // x is not zero, do the job2
...

我发现here的方法相同。但我看到两个问题:

  1. 随机幻数1e-7f(或上面链接的0.00005)。
  2. 代码难以阅读
  3. 这是一个常见的比较,我想知道是否有一个标准的简短方法来做到这一点。喜欢

     x.is_zero();
    

3 个答案:

答案 0 :(得分:5)

没有标准的方法,因为你是否想要将一个小数字视为零,取决于你如何计算数字和它的用途。这又取决于计算引入的任何误差的预期大小,也可能取决于确定原始输入的物理测量误差。

例如,假设您的值表示某些地图软件中的行程长度(以英里为单位)。然后你很乐意将1e-7视为等于零,因为在这种情况下它是一个非常小的数字:它是由于舍入错误或其他轻微不准确的原因而产生的。

另一方面,假设您的值代表某些电子显微镜软件中分子的大小(以米为单位)。那么你肯定想要将1e-7视为等于零,因为在那种情况下它是一个非常大的数字。

您应该首先考虑提供您的价值的合适准确度:错误条是什么,或者您可以合理显示多少重要数字。这将让你对使用什么样的容差进行测试,以便对零进行测试,尽管它仍然可能无法解决问题。对于地图软件,如果旅程小于某个固定值,您可以将旅程视为零,尽管该值本身可能取决于地图的分辨率。对于显微镜软件,如果两个尺寸之间的差异使得这些测量值的误差范围为零,则仍然可能 足以将它们描述为相同的尺寸。

答案 1 :(得分:4)

要将浮点值与0进行比较,只需比较它:

if (f == 0)
    // whatever

这种比较没有错。如果它没有按照你的预期行事,因为f的价值不是你想象的那样。它基本上与此问题相同:

int i = 1/3;
i *= 3;
if (i == 1)
    // whatever

这种比较没有错,但i的值不是1.几乎所有程序员都理解整数值的精度损失;很多人都不了解浮点值。

使用&#34;几乎相等&#34;而不是==是一种先进的技术;它经常导致意想不到的问题。例如,它不是传递性的;也就是说,a几乎等于bb几乎等于c 意味着a几乎等于c }。

答案 2 :(得分:2)

我不知道我的回答是否有用,我在irrlicht的irrmath.h中找到了这个,并且至今仍在引擎的mathlib中使用它:

const float ROUNDING_ERROR_f32 = 0.000001f;

//! returns if a equals b, taking possible rounding errors into account
inline bool equals(const float a, const float b, const float tolerance = ROUNDING_ERROR_f32)
{
        return (a + tolerance >= b) && (a - tolerance <= b);
}

作者通过“经过多次旋转,这是三角运算后的坐标破坏和直接比较可能导致故障”来解释这种方法。