Matlab中浮点数比较的最佳实践是什么?

16

显然,浮点数比较总是棘手的。我的(科学)代码中有很多断言检查,因此我经常需要检查总和是否等于1,以及类似的问题。

有没有一种快速简便/最佳实践的方法来执行这些检查?

我能想到的最简单的方法是构建一个定值容差的浮点比较自定义函数,但这对我来说似乎相当丑陋。我希望有一个内置的解决方案,或者至少是极其清晰和直观易懂的东西。

5个回答

11

我认为最有可能的情况是你需要自己编写一个函数。就像我经常用三个东西来运行计算向量测试一样:

最大绝对误差

return max(abs(result(:) - expected(:))) < tolerance

这会逐点计算最大绝对误差并告诉您是否小于某个容忍度。

最大过量误差计数

return sum( (abs(result(:) - expected(:))) < tolerance )

这将返回落在你容忍范围外的点数。也很容易修改以返回百分比。

均方根误差

return norm(result(:) - expected(:)) < rmsTolerance

由于存在许多比较浮点数数组的标准,我建议编写一个函数,该函数接受计算结果、期望结果、容差和比较方法。这样,您可以使检查非常紧凑,而且比尝试在注释中解释自己所做的事情要好得多。


4
通常使用eps来作为容差值是个不错的主意。另外,R2013a及以后版本的单元测试框架中有assertEqual语句可以帮助检查。 - Jonas
确实如此,但有时这可能不够,因为在某些计算过程中,您可能已经失去了精度多次。 - Phonon
谢谢,eps()听起来是个好主意。实际上我希望有一种在单元测试框架之外的assertEqual。 - zuiqo

10

如果输入非常大或非常小的数字,任何固定公差都会失败,最简单的解决方案是使用eps来获得双精度:

任何固定公差都会失败,如果你输入非常大或非常小的数字,最简单的解决方案是使用eps来获得双精度:

abs(A-B)<eps(A)*4

4是完全任意的数字,在大多数情况下足够使用。


5

我不知道有任何特殊的内置解决方案。也许可以使用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

2
你应该将数量级传递给 eps,因为 eps(10000) 比默认值 eps(1) 大。 - Jonas

0

我对xUnit有着良好的使用经验,它是Matlab的一个单元测试框架。安装后,您可以使用以下功能:

  • assertVectorsAlmostEqual(a,b)(检查向量之间的范数接近程度;可配置绝对/相对容差和合理的默认值)
  • assertElementsAlmostEqual(a,b)(同样的检查,但是逐个元素地进行比较--因此[1 1e-12][1 -1e-9]将与前者相等,但与后者不相等)。

它们经过了充分的测试,使用起来很快且易于阅读。函数名称相当长,但是使用任何像样的编辑器(或Matlab自带的编辑器),您都可以将它们写成assertV<tab>


-2

对于那些了解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)

1
这个问题涉及到MATLAB,而不是Python的numpy。请仔细阅读问题标题和标签。此外,对于那些不熟悉Python和numpy的人来说,这可能并不具有建设性,因此检查这些实现相当无用。 - rayryeng
我的经验是许多人都同时使用Matlab和Python,因此对于这些人来说,进行代码交叉检查非常有用。 - aquercia
根据我在StackOverflow上的经验,许多回答MATLAB问题的人并不了解Python。我可能是少数同时相对熟悉这两种语言的人之一,基于我的观点,这个答案并不有用。你可以选择留下它与否,但我会留下我的负评。这并不是因为我认为你的答案在技术上不正确,而是因为你在一个与标签不兼容的问题中提供了答案。 - rayryeng
2
然而,如果您将等效的 numpy 代码翻译成 MATLAB,那么这是一个非常有用的答案,我会倾向于点赞。这样,您不仅指出了 numpy 已经具备的功能,还为我们提供了在 MATLAB 中执行此操作的方法。 - rayryeng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接