Clear Filters
Clear Filters

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

4 views (last 30 days)
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
Stephen23
Stephen23 on 7 Sep 2017
giorgia calisti
giorgia calisti on 7 Sep 2017
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.

Accepted Answer

José-Luis
José-Luis on 7 Sep 2017
Edited: José-Luis on 7 Sep 2017
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.

More Answers (1)

Guillaume
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

Categories

Find more on Characters and Strings in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!