5

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

据我所知直接比较:

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
...

我在这里找到的方法相同。但我看到两个问题:

  1. 随机幻数 1e-7f(或上面链接中的 0.00005)。
  2. 代码更难阅读

这是一个常见的比较,我想知道是否有一个标准的短方法来做到这一点。喜欢

 x.is_zero();
4

3 回答 3

5

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

if (f == 0)
    // whatever

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

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

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

使用“几乎相等”代替==是一种先进的技术;它往往会导致意想不到的问题。例如,它不是传递的;也就是说,a几乎等于bb几乎等于c并不意味着几乎a等于c

于 2013-11-03T16:46:56.420 回答
5

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

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

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

您应该首先考虑显示您的值的合适准确度:误差线是多少,或者您可以合理显示多少有效数字。这将使您对针对零进行测试的容忍度有所了解,尽管它仍然可能无法解决问题。对于地图软件,如果旅程小于某个固定值,您可能会将其视为零,尽管该值本身可能取决于地图的分辨率。对于显微镜软件,如果两个尺寸之间的差异是零与这些测量的 95% 误差范围内,那可能仍然不足以将它们描述为相同的尺寸。

于 2013-11-03T16:49:13.630 回答
4

我不知道我的回答是否有用,我在 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);
}

作者用“多次旋转后,这是三角运算,坐标损坏,直接比较可能会导致错误”来解释这种方法。

于 2013-11-03T17:38:28.013 回答