Search code examples
rfloating-pointprecisionr-faq

acos(1) returns NaN for some values, not others


I have a list of latitude and longitude values, and I'm trying to find the distance between them. Using a standard great circle method, I need to find:

acos(sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2) * cos(long2-long1))

And multiply this by the radius of earth, in the units I am using. This is valid as long as the values we take the acos of are in the range [-1,1]. If they are even slightly outside of this range, it will return NaN, even if the difference is due to rounding.

The issue I have is that sometimes, when two lat/long values are identical, this gives me an NaN error. Not always, even for the same pair of numbers, but always the same ones in a list. For instance, I have a person stopped on a road in the desert:

Time  |lat     |long
1:00PM|35.08646|-117.5023
1:01PM|35.08646|-117.5023
1:02PM|35.08646|-117.5023
1:03PM|35.08646|-117.5023
1:04PM|35.08646|-117.5023

When I calculate the distance between the consecutive points, the third value, for instance, will always be NaN, even though the others are not. This seems to be a weird bug with R rounding.


Solution

  • Can't tell exactly without seeing your data (try dput), but this is mostly likely a consequence of FAQ 7.31.

    (x1 <- 1)
    ## [1] 1
    (x2 <- 1+1e-16)
    ## [1] 1
    (x3 <- 1+1e-8)
    ## [1] 1
    acos(x1)
    ## [1] 0
    acos(x2)
    ## [1] 0
    acos(x3)
    ## [1] NaN
    

    That is, even if your values are so similar that their printed representations are the same, they may still differ: some will be within .Machine$double.eps and others won't ...

    One way to make sure the input values are bounded by [-1,1] is to use pmax and pmin: acos(pmin(pmax(x,-1.0),1.0))