使用机器 epsilon 是否适合浮点相等测试?

发布于 2024-09-10 04:01:07 字数 1597 浏览 7 评论 0原文

这是测试浮点值相等:“精度”常量有标准名称吗?
有一个非常相似的问题


">Double.Epsilon 表示相等、大于、小于、小于或等于、大于或 众所周知,两个浮点值 xy 的相等测试应该看起来更像这样(而不是简单的 =):

abs(x - y ) epsilon   ,  其中epsilon是一些非常小的值。

如何选择epsilon的值?

显然最好为epsilon选择尽可能小的值,以获得最高的-相等性检查的可能精度。

例如,.NET 框架提供了一个常量 System.Double.Epsilon (= 4.94066 × 10-324),它代表最小的正 System .Double 大于零的值。

然而,事实证明这个特定值不能可靠地用作 epsilon,因为:

0  + System.Double.Epsilon ≠  0

1 + System.Double.Epsilon =  1   (!)

如果我理解正确的话,因为该常量小于 machine epsilon

<罢工> → 这是正确的吗?

→ 这是否也意味着我可以可靠地使用 epsilon := machine epsilon 进行相等性测试?

删除了这两个问题,因为上面链接的第二个 SO 问题已经充分回答了它们。


链接到的维基百科文章说,对于 64 位浮点数(即 double 类型(在许多语言中),机器 epsilon 等于:

2-53,  或大约。 0.000000000000000111(小数点后有 15 个零的数字)

→ 由此可知,所有 64 位浮点值都保证精确到 14 位(如果不是 15 位)吗?

This is a follow-up to Testing for floating-point value equality: Is there a standard name for the “precision” constant?.
There is a very similar question Double.Epsilon for equality, greater than, less than, less than or equal to, greater than or equal to.


It is well known that an equality test for two floating-point values x and y should look more like this (rather than a straightforward =):

abs( x - y ) < epsilon   ,   where epsilon is some very small value.

How to choose a value for epsilon?

It would obviously be preferable to choose for epsilon as small a value as possible, to get the highest-possible precision for the equality check.

As an example, the .NET framework offers a constant System.Double.Epsilon (= 4.94066 × 10-324), which represents the smallest positive System.Double value that is greater than zero.

However, it turns out that this particular value can't be reliably used as epsilon, since:

0  + System.Double.Epsilon ≠  0

1  + System.Double.Epsilon =  1   (!)

which is, if I understand correctly, because that constant is less than machine epsilon.


→ Is this correct?

→ Does this also mean that I can reliably use epsilon := machine epsilon for equality tests?

Removed these two questions, as they are already adequately answered by the second SO question linked-to above.


The linked-to Wikipedia article says that for 64-bit floating-point numbers (ie. the double type in many languages), machine epsilon is equal to:

2-53,   or approx. 0.000000000000000111 (a number with 15 zeroes after the decimal point)

→ Does it follow from this that all 64-bit floating point values are guaranteed to be accurate to 14 (if not 15) digits?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

血之狂魔 2024-09-17 04:01:08

过去,当我不得不使用 epsilon 值时,它比机器 epsilon 值大得多。

尽管它是针对 32 位双精度数(而不是 64 位双精度数),但我们发现我们的特定应用程序<中的大多数(如果不是全部)计算值都需要 10-6 的 epsilon 值/强>。

您选择的 epsilon 值取决于数字的范围。如果您正在处理非常大(例如 10+10),那么您可能需要更大的 epsilon 值,因为您的有效数字不会延伸到小数中很远部分(如果有的话)。如果您正在处理非常小(例如 10-10),那么显然您需要一个比这个更小的 epsilon 值。

您需要做一些实验,执行计算并检查输出值之间的差异。只有当您知道潜在答案的范围时,您才能为您的应用决定合适的值。

In the past when I have had to use an epsilon value it's been very much bigger than the machine epsilon value.

Although it was for 32 bit doubles (rather than 64 bit doubles) we found that an epsilon value of 10-6 was needed for most (if not all) calculated values in our particular application.

The value of epsilon you choose depends on the scale of your numbers. If you are dealing with the very large (10+10 say) then you might need a larger value of epsilon as your significant digits don't stretch very far into the fractional part (if at all). If you are dealing with the very small (10-10 say) then obviously you need an epsilon value that's smaller than this.

You need to do some experimentation, performing your calculations and checking the differences between your output values. Only when you know the range of your potential answers will you be able to decide on a suitable value for your application.

失与倦" 2024-09-17 04:01:08

可悲的事实是:没有适合浮点比较的 epsilon。如果您不想遇到严重的错误,请使用另一种方法进行浮点相等测试。

近似浮点比较是一个非常棘手的领域,并且 abs(x - y) abs(x - y) abs(x - y) abs(x - y) eps 方法仅适用于非常有限的值范围,主要是因为绝对差没有考虑比较值的大小,而且还因为两个浮点相减时发生有效数字抵消具有不同指数的值。

有更好的方法,使用相对差异或 ULP,但它们有自己的缺点和陷阱。阅读 Bruce Dawson 的优秀文章 比较浮点数, 2012 版 详细介绍了浮点比较究竟是多么棘手——恕我直言,这是任何进行浮点编程的人必读的内容!我确信已经花费了无数数千人年来找出由于幼稚的浮点比较而产生的微妙错误。

The sad truth is: There is no appropriate epsilon for floating-point comparisons. Use another approach for floating-point equality tests if you don't want to run into serious bugs.

Approximate floating-point comparison is an amazingly tricky field, and the abs(x - y) < eps approach works only for a very limited range of values, mainly because of the absolute difference not taking into account the magnitude of the compared values, but also due to the significant digit cancellation occurring in the subtraction of two floating-point values with different exponents.

There are better approaches, using relative differences or ULPs, but they have their own shortcomings and pitfalls. Read Bruce Dawson's excellent article Comparing Floating Point Numbers, 2012 Edition for a great introduction into how tricky floating-point comparisons really are -- a must-read for anyone doing floating-point programming IMHO! I'm sure countless thousands of man-years have been spent finding out the subtle bugs due to naive floating-point comparisons.

入画浅相思 2024-09-17 04:01:08

我还对正确的程序有疑问。然而我认为应该这样做:

abs(x - y) <= 0.5 * eps * max(abs(x), abs(y))

而不是:

abs(x - y) < eps

其原因源于机器 epsilon 的定义。使用 python 代码:

import numpy as np
real = np.float64
eps = np.finfo(real).eps

## Let's get the machine epsilon
x, dx = real(1), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

给出: eps = 2.220446e-16 dx = 1.110223e-16 eps*x/2 = 1.110223e-16

## Now for x=16
x, dx = real(16), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

现在给出: eps = 2.220446e-16 dx = 1.776357e-15 eps*x/2 = 1.776357e-15

## For x not equal to 2**n
x, dx = real(36), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

返回:eps = 2.220446e-16 dx = 3.552714e-15 eps*x/2 = 3.996803e-15

然而,尽管 dx 和 eps*x/2 之间存在差异,但我们看到dx <= eps*x/2
因此,它用于等式测试、在数值过程中测试收敛性时检查容差等。

这与以下内容类似:
www.ibiblio.org/pub/languages/fortran/ch1-8 .html#02,
但是,如果有人知道更好的程序,或者这里有什么不正确的地方,请务必指出。

I also have questions regarding what would be the correct procedure. However I believe one should do:

abs(x - y) <= 0.5 * eps * max(abs(x), abs(y))

instead of:

abs(x - y) < eps

The reason for this arises from the definition of the machine epsilon. Using python code:

import numpy as np
real = np.float64
eps = np.finfo(real).eps

## Let's get the machine epsilon
x, dx = real(1), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

Which gives: eps = 2.220446e-16 dx = 1.110223e-16 eps*x/2 = 1.110223e-16

## Now for x=16
x, dx = real(16), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

Which now gives: eps = 2.220446e-16 dx = 1.776357e-15 eps*x/2 = 1.776357e-15

## For x not equal to 2**n
x, dx = real(36), real(1)
while x+dx != x: dx/= real(2) ;

print "eps = %e  dx = %e  eps*x/2 = %e" % (eps, dx, eps*x/real(2))

Which returns: eps = 2.220446e-16 dx = 3.552714e-15 eps*x/2 = 3.996803e-15

However, despite the difference between dx and eps*x/2, we see that dx <= eps*x/2,
thus it serves the purpose for equality tests, checking for tolerances when testing for convergence in numerical procedures, etc.

Such is similar to what is in:
www.ibiblio.org/pub/languages/fortran/ch1-8.html#02,
however if someone knows of better procedures or if something here is incorrect, please do say.

最美的太阳 2024-09-17 04:01:07

如何选择 epsilon 的值?

简短回答:您可以选择一个适合您的应用程序需求的小值。

长答案:没有人知道您的应用程序进行了哪些计算以及您期望结果的准确程度。由于舍入误差总计机器 epsilon 几乎总是太大,因此您必须选择自己的值。根据您的需要,0.01 就足够了,或者 0.00000000000001 或更少就足够了。

问题是,您真的想要/需要对浮点值进行相等测试吗?也许你应该重新设计你的算法。

How to choose a value for epsilon?

Short Answer: You take a small value which fits your applications needs.

Long Answer: Nobody can know which calculations your application does and how accurate you expect your results to be. Since rounding errors sum up machine epsilon will be almost all times far too big so you have to chose your own value. Depending on your needs, 0.01 be be sufficient, or maybe 0.00000000000001 or less will.

The question is, do you really want/need to do equality tests on floating point values? Maybe you should redesign your algorithms.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文