What are the best practices for floating-point comparisons in Matlab?

后端 未结 5 930
时光取名叫无心
时光取名叫无心 2020-12-03 11:02

Obviously, float comparison is always tricky. I have a lot of assert-check in my (scientific) code, so very often I have to check for equality of sums to one, and similar is

相关标签:
5条回答
  • 2020-12-03 11:26

    Any fixed tolerance will fail if you put in very large or very small numbers, simplest solution is to use eps to get the double precision:

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

    The 4 is a totally arbitrary number, which is sufficient in most cases.

    0 讨论(0)
  • 2020-12-03 11:36

    I have had good experience with xUnit, a unit test framework for Matlab. After installing it, you can use:

    • assertVectorsAlmostEqual(a,b) (checks for normwise closeness between vectors; configurable absolute/relative tolerance and sane defaults)
    • assertElementsAlmostEqual(a,b) (same check, but elementwise on every single entry -- so [1 1e-12] and [1 -1e-9] will compare equal with the former but not with the latter).

    They are well-tested, fast to use and clear enough to read. The function names are quite long, but with any decent editor (or the Matlab one) you can write them as assertV<tab>.

    0 讨论(0)
  • 2020-12-03 11:39

    For those who understand both MATLAB and Python (NumPy), it would maybe be useful to check the code of the following Python functions, which do the job:

    numpy.allclose(a, b, rtol=1e-05, atol=1e-08)
    numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
    
    0 讨论(0)
  • 2020-12-03 11:47

    I think it's most likely going to have to be a function you write yourself. I use three things pretty constantly for running computational vector tests so to speak:

    Maximum absolute error

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

    This calculates maximum absolute error point-wise and tells you whether that's less than some tolerance.

    Maximum excessive error count

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

    This returns the number of points that fall outside your tolerance range. It's also easy to modify to return percentage.

    Root mean squared error

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

    Since these and many other criteria exist for comparing arrays of floats, I would suggest writing a function which would accept the calculation result, the expected result, the tolerance and the comparison method. This way you can make your checks very compact, and it's going to be much less ugly than trying to explain what it is that you're doing in comments.

    0 讨论(0)
  • 2020-12-03 11:48

    Don't know any special build in solution. Maybe something with using eps function?

    For example as you probably know this will give False (i.e. 0) as a result:

    >> 0.1 + 0.1 + 0.1 == 0.3
    
    ans =
    
         0
    

    But with eps you could do the following and the result is as expected:

    >> (0.1+0.1+0.1) - 0.3  < eps     
    
    ans =
    
         1
    
    0 讨论(0)
提交回复
热议问题