How can I compare numbers for equality within a tolerance?

485 views (last 30 days)
I need to compare two numeric matrices. A built-in function such as EQ (==) finds two numbers to be different even they differ by only 1e-15. Therefore, I was looking for another built-in function that could take a tolerance as an input argument, and return “true” when the absolute difference is below the tolerance threshold. How can I do that in MATLAB?

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 8 Dec 2023
Edited: MathWorks Support Team on 14 Dec 2023
In MATLAB R2015a, MathWorks introduced the built-in function "ismembertol" which compares members of a set within a tolerance.
For example, you can compare "A" and "B" to determine if their absolute difference is less than 1e-7 by using the following command:
ismembertol(A, B, 1e-7)
For more information about "ismembertol", please see the link below:
The ability to compare numeric values to within a tolerance is not available as a built-in function in MATLAB R2014b and earlier. As a workaround to avoid issues resulting from roundoff error, you can compare the absolute difference of the operands to a tolerance. Instead of:
A==B
you can use the following:
abs(A-B) < 1e4*eps(min(abs(A),abs(B)))
There are also a couple of entries for this on the MATLAB Central file exchange. These files are not produced by or supported by MathWorks, so any questions should be directed to the authors, however other customers have found these to be useful.
"IsNear" function:
"isalmost" function:
A similar approach is used by the attached file (see below), which also has a provision for handling NaN values.
  5 Comments
Walter Roberson
Walter Roberson on 11 Aug 2021
No.
Suppose you take
format long g
F = 10;
A1 = 1/F;
A2 = A1*(1+eps);
C1 = 0; C2 = 0;
N = F;
for K = 1 : N
C1 = C1 + A1;
C2 = C2 + A2;
end
algebraically_expected = N/F
algebraically_expected =
1
low_side = C1
low_side =
1
high_side = C2
high_side =
1
low_difference = low_side - algebraically_expected
low_difference =
-1.11022302462516e-16
high_difference = high_side - algebraically_expected
high_difference =
6.66133814775094e-16
high_side - low_side
ans =
7.7715611723761e-16
A2-A1
ans =
2.77555756156289e-17
(A2-A1)*F
ans =
2.77555756156289e-16
That last tells you that if you were to have algebrically perfect additions, then with A2 being larger than A1, you would expect 2.7E-16 difference between F additions of A2 compared to F additions of A1. But high_side - low_side shows that in reality you get an error about 3 1/2 times as large.
So errors in representation accumulate, and they can accumulate more than is at first obvious. If you do N calculations, the accumulated error might be more than N times the individual error.
Therefore, when you are comparing floating point numbers, it is not typically a good idea to use (individual error times number of operations) as the tolerance, and to instead use a multiple of that. But what multiple?
The multiple that is "reasonable" depends upon the kind of operations being done. If you are just doing additions, then the multiple might be rather small. If you are doing matrix operations then you should think about the "condition number".
I did run into a situation a couple of weeks ago in which a multiple of about 5000*eps was appropriate; I know I posted the code, but unfortunately my memory is not giving me enough context to find it at this time.

Sign in to comment.

More Answers (0)

Products


Release

R2012b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!