这是测试浮点值相等的后续行动:“精度”常量是否有标准名称? Double.Epsilon有一个非常相似的问题,即大于,小于,小于或等于,大于或等于 .
众所周知,对两个浮点值x和y的相等测试看起来应该更像这样(而不是简单的=):
abs(x - y)<epsilon,其中epsilon是一个非常小的值 .
How to choose a value for 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个零的数字)
→ Does it follow from this that all 64-bit floating point values are guaranteed to be accurate to 14 (if not 15) digits?
4 回答
Short Answer: 您需要一个适合您应用需求的小值 .
Long Answer: 没有人能够知道您的应用程序执行了哪些计算以及您希望结果如何 accurate . 由于舍入错误总结机器epsilon几乎所有时间都太大,所以你必须选择自己的值 . 根据您的需要,0.01是足够的,或者可能是0.00000000000001或更少 .
问题是, do you really want/need to do equality tests on floating point values ?也许你应该重新设计你的算法 .
在过去,当我不得不使用epsilon值时,它比机器epsilon值大得多 .
虽然它是32位双精度(而不是64位双精度),但我们发现 our particular application 中的大多数(如果不是全部)计算值需要10-6的epsilon值 .
您选择的epsilon值取决于您的数字的比例 . 如果您正在处理 very large (10 10说)那么您可能需要更大的epsilon值,因为您的有效数字不会延伸到小数部分(如果有的话) . 如果你正在处理 very small (10-10说)那么显然你需要一个比这个小的epsilon值 .
您需要进行一些实验,执行计算并检查输出值之间的差异 . 只有当您知道潜在答案的范围时,您才能决定合适的值 for your application .
可悲的事实是: There is no appropriate epsilon for floating-point comparisons. 如果你不想遇到严重的错误,请使用另一种方法进行浮点相等测试 .
近似浮点比较是一个非常棘手的领域,并且
abs(x - y) < eps
方法仅适用于非常有限的值范围,主要是因为绝对差异没有考虑比较值的大小,而且还由于显着的数字取消在使用不同指数减去两个浮点值时发生 .有更好的方法,使用相对差异或ULP,但它们有自己的缺点和陷阱 . 阅读Bruce Dawson的优秀文章Comparing Floating Point Numbers, 2012 Edition,了解如何进行棘手的浮点比较 - 对于任何进行浮点编程的人都必须阅读恕我直言!我敢肯定,由于天真的浮点比较,我花了数千年的时间来寻找细微的错误 .
关于什么是正确的程序,我也有疑问 . 不过我认为应该这样做:
代替:
造成这种情况的原因来自机器epsilon的定义 . 使用python代码:
给出了:
eps = 2.220446e-16 dx = 1.110223e-16 eps*x/2 = 1.110223e-16
现在给出:
eps = 2.220446e-16 dx = 1.776357e-15 eps*x/2 = 1.776357e-15
返回:
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,但是如果有人知道更好的程序或者这里的东西是不正确的,请说 .