Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm having some problems with Position.

Sometimes it will give an empty list instead of the actual position of the element I am looking for when that element is specified through some other code but will return the correct position when the element is specified directly as a number as in the minimum working example below.

data = {{0.1, 0.0001683}, {0.2, 0.00035754}, {0.3, 0.00056711}, {0.4, 
   0.00078986}, {0.5, 0.0010333}, {0.6, 0.0010333}, {0.7, 
   0.0015758}, {0.8, 0.0018738}, {0.9, 0.0022054}, {1., 
   0.0025706}, {1.1, 0.0029788}, {1.2, 0.0034366}, {1.3, 
   0.0039831}, {1.4, 0.0046433}, {1.5, 0.0055203}, {1.6, 
   0.0068061}, {1.7, 0.010939}, {1.8, 0.031246}, {1.9, 0.054948}, {2.,
    0.076556}, {2.1, 0.098521}, {2.2, 0.12551}, {2.3, 0.1585}, {2.4, 
   0.1921}, {2.5, 0.22544}, {2.6, 0.25798}, {2.7, 0.28992}, {2.8, 
   0.32051}, {2.9, 0.35095}, {3., 0.38104}}

interpol = Interpolation[data];

q = FindRoot[interpol[x] == 0.159, {x, 2.9}][[1, 2]]
(*2.3015*)

xlow = Floor[q, 0.1]
(*2.3*)

Position[data[[All, 1]], xlow]
(*{}*)

Position[data[[All, 1]], 2.3]
(*{{23}}*)

When running v8 on xP this code gives {} for the first output and {{23}} for the second.

This type of error is referenced in the Possible Issues section of the documentation for Position in v8 and v9 but no advice is given.

In[1] := Position[Range[-1, 1, 0.05], 0.1]
Out[1] = {}

I've tried putting N everywhere I can to solve it as I thought it could just be a precision or representation issue ( i.e. 2.3 vs 23/10 ) but with no success. Does anyone have nifty work around or solution to this that I am missing please?

share|improve this question
2  
Would Position[data[[All, 1]], Nearest[data[[All, 1]], xlow][[1]]] be acceptable ? –  b.gatessucks Dec 7 '12 at 10:25
    
It works so it most certainly would be acceptable! Thanks for the fast reply. –  fizzics Dec 7 '12 at 10:40
1  
Since I believe the correct answer is to use Chop (see below), it's also worth pointing to this and this. –  Jens Dec 8 '12 at 18:26
add comment

2 Answers 2

up vote 10 down vote accepted

Position is looking for an exact match (pseudo-SameQ), rather than a numeric one.
You will get the result you want with:

Position[data[[All, 1]], _?(# == xlow &)]

Or:

Position[data[[All, 1]], x_ /; x == xlow]

Generally you should use Equal (short form ==) any time you are trying to mach Real numbers, to allow for small rounding errors.

Using the pattern 0 | 0. is not sufficient; See this for examples.


For an excellent treatment of the problems of matching inexact numbers see:

Instability in DeleteDuplicates and Tally

share|improve this answer
    
Thanks for the fast reply. Both of those do the job perfectly but I'm a bit confused by the structure you use in the first one. Wouldn't the _? return a True value instead of a numeric? The second structure I don't fully understand either as I don't see how Position knows to loop over x and compared each term. There is obviously more functionality built in than I appreciate –  fizzics Dec 7 '12 at 10:37
2  
@fizzics Both _?(# == xlow &) and x_ /; x == xlow are patterns, which is what Position needs as a second argument. _?testfunction is a pattern for any single expression for which testfunction yields True when applied. x_ /; expr is a pattern for any single expression, which we locally name x, for which expr evaluates to True; if x appears in expr the local definition is used. Read the documentation for Pattern, PatternTest, and Condition, then see this question. Return with any further questions. –  Mr.Wizard Dec 7 '12 at 11:27
add comment

One alternative approach that is very powerful when dealing with approximate real numbers hasn't been mentioned yet: use Chop or Threshold.

These two functions are intended for just the type of situations you describe, so I would always try them first:

In your example, this simple command works:

Position[Chop[data[[All, 1]] - xlow], 0]

{{23}}

Instead of finding xlow, I reformulated the problem so that you find 0 in the list of differences with xlow.

share|improve this answer
    
Excellent recommendation. Numeric methods are almost always faster. –  Mr.Wizard Dec 8 '12 at 22:22
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.