acos(1)返回某些值的NaN,而不是其他值

时间:2012-12-24 22:55:16

标签: r floating-point precision r-faq

我有一个纬度和经度值列表,我正在尝试找到它们之间的距离。使用标准的大圆方法,我需要找到:

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

将其乘以我使用的单位的地球半径。只要我们取acos的值在[-1,1]范围内,这就有效。如果它们甚至略微超出此范围,它将返回NaN,即使差异是由于四舍五入。

我遇到的问题是,有时,当两个纬度/经度值相同时,这会给我一个NaN错误。并非总是如此,即使对于同一对数字,但在列表中总是相同的数字。例如,我有一个人停在沙漠中的一条路上:

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

当我计算连续点之间的距离时,例如,第三个值将始终为NaN,即使其他点不是。{{1}}。这似乎是R舍入的一个奇怪的错误。

2 个答案:

答案 0 :(得分:8)

在没有看到您的数据的情况下无法准确判断(尝试dput),但这很可能是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

也就是说,即使您的值非常相似以至于它们的打印表示相同,它们仍然可能会有所不同:有些会在.Machine$double.eps之内而有些则不会......

确保输入值受[-1,1]限制的一种方法是使用pmaxpminacos(pmin(pmax(x,-1.0),1.0))

答案 1 :(得分:0)

一个简单的解决方法是使用pmin(),如下所示:

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

现在可以确保精度损失导致的值不高于1。

然而,这并不能解释正在发生的事情。

(编辑:Matthew Lundberg指出我需要使用pmin来使用矢量化输入进行拖曳工作。这解决了使其工作的问题,但我仍然不确定为什么它不正确地舍入。)