16 views (last 30 days)

Show older comments

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.

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.

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

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

Start Hunting!