【发布时间】:2014-05-23 08:38:39
【问题描述】:
显然,浮点比较总是很棘手。我的(科学)代码中有很多断言检查,所以我经常必须检查总和是否相等以及类似的问题。
是否有一种快速简便/最佳实践的方法来执行这些检查?
我能想到的最简单的方法是为固定容差浮动比较构建一个自定义函数,但这对我来说似乎很难看。我更喜欢内置的解决方案,或者至少是非常清晰易懂的解决方案。
【问题讨论】:
标签: matlab floating-point
显然,浮点比较总是很棘手。我的(科学)代码中有很多断言检查,所以我经常必须检查总和是否相等以及类似的问题。
是否有一种快速简便/最佳实践的方法来执行这些检查?
我能想到的最简单的方法是为固定容差浮动比较构建一个自定义函数,但这对我来说似乎很难看。我更喜欢内置的解决方案,或者至少是非常清晰易懂的解决方案。
【问题讨论】:
标签: matlab floating-point
我认为它很可能必须是您自己编写的函数。可以这么说,我经常使用三样东西来运行计算向量测试:
最大绝对误差
return max(abs(result(:) - expected(:))) < tolerance
这会逐点计算最大绝对误差,并告诉您这是否小于某个容差。
最大错误计数
return sum( (abs(result(:) - expected(:))) < tolerance )
这将返回超出公差范围的点数。修改返回百分比也很容易。
均方根误差
return norm(result(:) - expected(:)) < rmsTolerance
由于存在这些和许多其他标准来比较浮点数组,我建议编写一个函数来接受计算结果、预期结果、容差和比较方法。通过这种方式,您可以使您的检查变得非常紧凑,并且比试图解释您在 cmets 中所做的事情要简单得多。
【讨论】:
eps 表示容差通常是个好主意。此外,R2013a 及更高版本在单元测试框架中具有 assertEqual 语句,这将有所帮助。
如果输入非常大或非常小的数字,任何固定公差都会失败,最简单的解决方案是使用eps 来获得双精度:
abs(A-B)<eps(A)*4
4 是一个完全任意的数字,在大多数情况下就足够了。
【讨论】:
不知道任何特殊的内置解决方案。也许使用eps 函数?
例如,您可能知道这将导致 False(即0):
>> 0.1 + 0.1 + 0.1 == 0.3
ans =
0
但使用 eps 你可以执行以下操作,结果符合预期:
>> (0.1+0.1+0.1) - 0.3 < eps
ans =
1
【讨论】:
eps,因为eps(10000) 大于默认值eps(1)。
我在 xUnit 方面有很好的经验,这是一个 Matlab 的单元测试框架。安装好之后就可以使用了:
assertVectorsAlmostEqual(a,b)(检查向量之间的 normwise 接近度;可配置的绝对/相对容差和合理的默认值)assertElementsAlmostEqual(a,b)(相同的检查,但每个条目都按元素进行 - 所以[1 1e-12] 和 [1 -1e-9] 将与前者比较,但与后者不相等)。它们经过充分测试,使用速度快且清晰易读。函数名称很长,但使用任何像样的编辑器(或 Matlab 编辑器)您都可以将它们写为assertV<tab>。
【讨论】:
对于同时了解 MATLAB 和 Python (NumPy) 的人来说,检查以下 Python 函数的代码可能会很有用:
numpy.allclose(a, b, rtol=1e-05, atol=1e-08)
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
【讨论】:
numpy。仔细阅读问题标题和标签。此外,这对于那些不熟悉 Python 和numpy 的人来说可能没有建设性,因此检查这些的实现是没有用的。
numpy 代码翻译到 MATLAB,那么这是一个非常有用的答案,我倾向于投票。这样,您不仅可以指出 numpy 已有的功能,而且还为我们提供了在 MATLAB 中执行此操作的方法。