MATLAB Answers

0

Why does == not work with decimal indexed for loop?

Asked by giorgia calisti on 7 Sep 2017
Latest activity Commented on by giorgia calisti on 7 Sep 2017
Hi everyone,
I am working with a simple data vector and I need to find the occurrences of certain values. Here is a simplified version of the code, which amounts to a for loop and an equality check:
data=[1.5 1.6 1.7 1.8 1.9 2 2.1 2.2];
%this does not work
for index=1.4:0.1:2.3
output=find(data==index)
end
%this works!
for index=1.5:0.1:2.2
output=find(data==index)
end
Running the code I see that in the first case, where only the first and last check should give an empty result, also other iterations give the "1×0 empty double row vector" output. For example, given that index=94.6 during debug, if I write the same line as "find(data==index)" it fails, if I write it with the corresponding index value it works (find(data==94.6) works). The positions where the check fails are always the same. The second for loop, with all the items matching, never fails.
Could it be a problem with the double format precision with logical operators? I have tried it in Matlab R2017a and R2013a, on different computers. I also tried to rewrite the same code without the find function, and the result is the same. If I change both data and index ranges, the behavior is the same but the check fails at different positions. All the numbers are in double format. If I multiply everything by 10, so that the numbers are integers, both loops work fine.
I would like to understand why, with decimal numbers, it doesn't work in just ONE case, the one where not all the numbers have a match.

  2 Comments

Thank you both José-Luis and Guillaume for your complete replies. I would accept both answers if I could, thanks again!

Sign in to comment.

2 Answers

Answer by José-Luis
on 7 Sep 2017
Edited by José-Luis
on 7 Sep 2017
 Accepted Answer

From the documentation:
"x = j:i:k creates a regularly-spaced vector x using i as the increment between elements. The vector elements are roughly equal to [j,j+i,j+2*i,...,j+m*i] where m = fix((k-j)/i)."
Emphasis on the roughly equal : You are running into the joys of double precision arithmetic. You should avoid comparing double precision numbers directly and use a tolerance.
You could use eps() to determine an adequate order of magnitude for the tolerance.

  0 Comments

Sign in to comment.


Answer by Guillaume
on 7 Sep 2017

What you're seeing is expected and is inherent to the way numbers are stored on computers. You'll see the same behaviour with other programming languages.
This is actually a FAQ and is all down to the fact that numbers can't all be represented exactly (particularly 0.1).
The answer is then to never use == to compare floating point values (it's fine for integers) but always use a small tolerance appropriate for the magnitude of numbers you're using.
In your case:
tolerance = 1e-20; %much smaller than your numbers magnitude
for index = 1.4:0.1:2.3
output = find(abs(data - index) <= tolerance); %check that the difference between the numbers is smaller than the tolerance
end

  0 Comments

Sign in to comment.