MATLAB: using the find function to get indices of a certain value in an array

前端 未结 3 2035
面向向阳花
面向向阳花 2021-01-16 21:28

I have made an array of doubles and when I want to use the find command to search for the indices of specific values in the array, this yields an empty matrix which is not w

相关标签:
3条回答
  • 2021-01-16 21:49

    By default, each element of a numerical matrix in Matlab is stored using floating point double precision. As you surmise in the question format short and format long merely alter the displayed format, rather than the actual format of the numbers.

    So if y1 is created using something like y1 = rand(100, 1), and you want to find particular elements in y1 using find, you'll need to know the exact value of the element you're looking for to floating point double precision - which depending on your application is probably non-trivial. Certainly, peaks=find(y1==0.8236) will return the empty matrix if y1 only contains values like 0.823622378...

    So, how to get around this problem? It depends on your application. One approach is to truncate all the values in y1 to a given precision that you want to work in. Funnily enough, a SO matlab question on exactly this topic attracted two good answers about 12 hours ago, see here for more.

    If you do decide to go down this route, I would recommend something like this:

    a = 1e-4 %# Define level of precision
    y1Round = round((1/a) * y1); %# Round to appropriate precision, and leave y1 in integer form
    Index = find(y1Round == SomeValue); %# Perform the find operation
    

    Note that I use the find command with y1Round in integer form. This is because integers are stored exactly when using floating point double, so you won't need to worry about floating point precision.

    An alternative approach to this problem would be to use find with some tolerance for error, for example:

    Index = find(abs(y1 - SomeValue) < Tolerance);
    

    Which path you choose is up to you. However, before adopting either of these approaches, I would have a good hard look at your application and see if it can be reformulated in some way such that you don't need to search for specific "real" numbers from among a set of "reals". That would be the most ideal outcome.

    EDIT: The code advocated in the other two answers to this question is neater than my second approach - so I've altered it accordingly.

    0 讨论(0)
  • 2021-01-16 22:09

    Testing for equality with floating-point numbers is almost always a bad idea. What you probably want to do is test to see which numbers are close enough to the target value:

    peaks = find( abs( y - .8236 ) < .0001 );
    
    0 讨论(0)
  • 2021-01-16 22:12

    The problem is indeed with the precision. The array that you see displayed is not the actual array, as the actual array has more digits for each of the numbers. Changing the format just changes the way in which the array is displayed, so it doesn't solve the problem.

    You have two options, either modify the array or modify what you are looking for. It is probably better to modify what you are looking for, since then you are not changing the actual values.

    So instead of looking for equality, you can look for proximity (so the difference between the number you are searching for and the number in the array is at most some small epsilon):

    peaks = find( abs(y1-0.8236) < epsilon )
    

    In general, when you are dealing with floats, always try to avoid exact comparisons and use some error thresholds, since the representation of these numbers is limited so they are often stored with small inaccuracies.

    0 讨论(0)
提交回复
热议问题