比较浮动时,您称差异阈值为多少?


10

我现在正在比较Java中的浮点数,最简单的公式是:

Math.abs(a - b) < THRESHOLD

将变量命名为差异阈值时,应将其命名为delta还是epsilon?具体来说,对于浮点数可以表示的最小值,正确的两项是哪一项?

术语“编程语言”是特定的还是跨语言通用的?


1
替代术语:“精度”,“分辨率”。我完全喜欢这些;),因为它们听起来不太技术性。
stakx

1
题外话:《浮点指南》建议不要使用这种类型的近似相等比较。
stakx

1
@stakx-您建议的术语不正确,并且与OP询问的含义不同。问题是详细的,是的,但它听命基于外部基准和它与浮点值打交道时具有相关性节目。它具有建设性和主题性。

1
@ GlenH7:我从未说过这个问题不是一个好问题,或者无法回答。实际上,我是对此提出支持的人。而且由于您声称我建议的(公认的不太精确)术语是错误的,所以我有兴趣了解为什么会这样。
stakx

@stakx-表示您已投票决定关闭表示歉意。目前,我对该问题的四次接近投票有更多反应。

Answers:


18

Epsilon数学和工程学

在数学和工程学方面:

  • 通常使用Delta来表示差异,该差异可以是任何比例。
  • Epsilon通常用于表示可忽略的数量。

epsilon似乎更适合您的情况。


Epsilon计算机科学

特别是在计算机科学中,“ε”一词也指机器espilon,它测量1.0f和最小地大于的浮子之间的差1.0f。后一个数字1.00000011920928955078125f用于Java中的float,可以通过以下方式计算:

float f = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1);

机器epsilon的定义与上述epsilon的一般用法一致。


比较浮点数

但是请注意,在比较浮点数的“接近度”之前,您需要了解它们的比例。两个非常大且据说非常不同的浮点数可以相等:

9223372036854775808f == 9223372036854775808f + 1000000000f; //this is true!

相反,在两个小的浮子之间可能有许多可能的浮子值(和几个数量级),它们之间的差值仅取决于机器epsilon。在下面的示例中,存在10,000,000之间可用的浮点值smallf,但它们的区别在于仍远低于机器最小:

float small = Float.MIN_VALUE; // small = 1.4E-45
float f = Float.intBitsToFloat(Float.floatToIntBits(small) + 100000000); // f = 2.3122343E-35
boolean b = (f - small < 0.00000011920928955078125f); //true!

GlenH7的答案中链接的文章进一步研究了浮点比较,并提出了克服这些问题的几种解决方案。


2
-1:在科学计算软件中,Epsilon指的是机器epsilon或相对epsilon(请参见同一文章)。通常,这不是用于接受近似相等的数量,因为舍入误差是机器ε或相对ε的倍数,通常比其大几个数量级。
rwong

1
@rwong这是epsilon一词的一种专业化,还有很多其他的。一般来说,在工程学中,epsilon确实指的是少量或错误,而Machine epsilon与该想法兼容。
assylias 2013年

@assylias在具有标准定义的上下文中使用具有标准定义的名称,但对于与标准定义不对应的内容,则表示收到了问题。
AProgrammer

@AProgrammer我不同意epsilon的一般定义不适用于计算。
assylias

1
@assylias:感谢您的澄清。我已经删除了-1。
rwong

16

在数学中,delta用于表示与某个值的差异,epsilon用于表示任意误差值。在这种情况下,epsilon将是常规名称。


8

要直接回答您的问题,您需要使用术语epsilon。更准确地说,它是machine epsilon常用的用法,但会删除“ machine”而只是使用epsilon

在我的本地副本中,float.h我看到:

#define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */  
#define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */  
#define LDBL_EPSILON    DBL_EPSILON             /* smallest such that 1.0+LDBL_EPSILON != 1.0 */

并且相关的注释清楚地表明epsilon是您所指的术语。

但是,我们也可以依靠其他一些外部参考来验证该epsilon术语是否正确。看到这里这里这里,最后是SO查询标记的这种组合。我找不到直接引用IEEE 754标准的参考。


您没有询问,但是我发现此参考资料与您提供的用于阐明问题的示例非常相关。

看一下Valve的Bruce Dawson撰写的有关比较浮点值的博客文章,以了解为什么您不想使用建议的比较。

该文章中包含很多信息,但这是此处最相关的摘录:

如果比较浮点数是否相等是一个坏主意,那么如何检查它们的差值是否在某个误差范围或epsilon值之内,如下所示:

bool isEqual = fabs(f1 – f2) <= epsilon;

通过此计算,我们可以表达两个浮点足够接近的概念,以使我们希望它们相等。但是我们应该为epsilon使用什么值?
鉴于上面的实验,我们可能会想在总和中使用误差,大约为1.19e-7f。实际上,float.h中甚至有一个具有确切值的定义,它称为FLT_EPSILON。
显然就是这样。头文件真让人发声,FLT_EPSILON是一个真正的epsilon!
除了那是垃圾。对于介于1.0和2.0之间的数字,FLT_EPSILON表示相邻浮点数之间的差。对于小于1.0的数字,FLT_EPSILON的epsilon很快会变得太大,而如果数字足够小,则FLT_EPSILON可能会比您正在比较的数字大!

Dawson在比较浮点数和处理像这样的非常小的值时还涉及了许多其他复杂性的考虑,因此,我鼓励您阅读他的文章的其余部分。


您可能需要澄清答案的第一部分:Bruce的文章已经解释了为什么不应该使用恒定epsilon(例如头文件中定义的epsilon)进行公差比较的原因。同样,在许多情况下,不必担心几百万个ULP的错误,因为在大多数应用程序中,我们关心的是有效数字而不是最低有效数字的错误,因为双精度已经给与了比我们关心的数字还要多。
rwong

@rwong-在我读到它时,问题是要确定用于常量名称的正确术语。这就是为什么我提供了float.h参考以及其他一些用于加工epsilon的原因。Dawson的文章是我在搜索IEEE 754参考文献时发现的,并且我认为与OP simplest formula进行比较很相关。许多人第一次使用该方法,而我之所以包含Dawson的文章,是因为它确实涉及比较有多难的细微差别。因此,我尝试直接回答该问题,然后指出为什么不这样使用它。

5

这是一个错误函数;绝对误差通常被称为ε(ε)或Δ X为一些数量X:

ε = |预期-实际|

Δ X = | x 0x  |

相对误差有时称为η(eta):

η = | 1 −实际/预期|

出于编程目的,(absoluteErrorrelativeError/或某些缩写)更具描述性。如果要断言该误差小于某个值,则将该值简称为阈值公差

看到:


3

我称之为“宽容”。

也许这不是数学上正确的术语,但是您问这个问题的事实对我而言意味着“ delta”和“ epsilon”都不是一个好变量。

以我的经验,最好使用对实际阅读代码的人有意义的标识符名称。如果完全正确的名称意味着读者需要在Wikipedia上查找它才能理解它的意思,那又有什么用呢?


+1。我始终希望人们能向同事询问有关这些命名问题的信息,并希望在此处发布。
MarkJ

6
-1,比起避免使用约定更好地学习约定。
djechlin

+1,因为这与我发布此问题的原因完全相同。
NobleUplift 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.