2013-11-03 71 views
3

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

据我所知直接的比较:

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. 代码更难阅读

这是这样一个共同的比较,我想知道是否有这样做一个标准的一小段路。像

x.is_zero(); 
+1

你的用例是什么?为什么你将一个浮点数比较为零? –

+6

不,没有标准,因为epsilon的适当值取决于应用程序。 – Barmar

+0

这取决于你想要做什么。数字从哪里来?为什么它重要,如果它是零? job1不能工作时,是否有限制? –

回答

3

要以0比浮点值,只是比较吧:

if (f == 0) 
    // whatever 

没有什么错与此相比。如果它没有达到你期望的效果,那是因为f的价值不是你认为的。它本质上是相同的问题,因为这样的:

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

有什么不妥比较的,但i值不为1,几乎所有的程序员理解的精度与整数值的损失;许多人不明白它与浮点值。

使用“几乎相等”而不是==是一种先进技术;它往往会导致意想不到的问题。例如,它不是传递性的;即a差不多等于bb差不多等于c不等于表示a差不多等于c

+0

我明白了。谢谢。 – klm123

+1

这是错误的答案。浮点印象不如整数截断那样清楚明显。程序员应该将浮点视为不可预测的。 – Phlip

+2

@Phlip:不,程序员应该在使用浮点数时理解错误的来源,并设计适当容差的算法。 –

5

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

例如,假设您的值代表某些地图软件中旅程的英里数。那么你很乐意把1e-7等于零,因为在这种情况下,它是一个非常小的数字:它是由于舍入误差或其他原因造成的轻微的不精确性而出现的。另一方面,假设您的数值代表某些电子显微镜软件中以米为单位的分子大小。那么你当然不要想要把1e-7等于零,因为在这种情况下,它是一个非常大的数字。

您应该首先考虑什么是合适的准确度来呈现您的价值:错误栏是什么,或者您可以合理显示多少有效数字。这会让你了解什么样的容忍度适合于零测试,尽管它仍然不能解决这个问题。对于地图绘制软件来说,如果行程小于某个固定值,您可能会将行程视为零,但该值本身可能取决于地图的分辨率。对于显微镜软件来说,如果两种尺寸之间的差异是这些测量结果的95%误差范围为零,那么仍然可能不足以将它们描述为相同的尺寸。

2

我不知道是否我的回答有用,我发现这Irrlicht的的irrmath.h,仍然使用它在发动机的mathlib直到nowdays:

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); 
} 

笔者通过“许多转后,解释这种方法,这是三角运算的坐标转换和直接比较可能导致错误“。

+0

这正是我使用的,请看帖子。 – klm123

+0

@ klm123我认为这里的要点是你应该提供的'tolerance'参数。有一个数字常量的默认值,它会产生稍微的反作用,我想,或者没有默认值,或者使用一个sentinel值,然后有一个可修改的默认值(当给定sentinel值时使用)。 – hyde

相关问题