【问题标题】:acos(1) returns NaN for some values, not othersacos(1) 为某些值返回 NaN,而不是其他值
【发布时间】:2012-12-11 04:02:03
【问题描述】:

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

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,即使其他值不是。这似乎是 R 舍入的一个奇怪错误。

【问题讨论】:

  • 该函数适用于向量;例如,我会使用 dist(lat(1:5), long(1:5),lat(2:6), long(2:6)) 作为函数 dist(lat1, long1, lat2,长2)。
  • @EricPostpischil 语言不同,没有提供适用于 R 的解决方案。

标签: r floating-point precision r-faq


【解决方案1】:

没有看到你的数据就无法准确判断(试试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] 限制的一种方法是使用 pmax 和 pmin:acos(pmin(pmax(x,-1.0),1.0))

【讨论】:

  • 但在源数据中,它们完全相同。精度损失完全在 R 中引入 - 我检查过。 (即使不是,该表达式在数学上也不可能大于 1。)
  • 另外,是否有解决方法?我需要让它工作,我的解决方案将它取消矢量化......
  • 我们需要查看确切的工作流程才能弄清楚发生了什么。如果(例如)您读入的 CSV 文件中的数字相同,那么之后它们确实会相同,但任何算术运算都可能导致差异——您仔细阅读常见问题解答了吗?
  • 我从 dbf 中读取它们,但我的假设是即使精度损失是可能的,对于相同的值它也会是相同的输出。
  • 对于相同的输入值,您确实应该得到相同的输出。如果您可以向我们展示一个可重现的分歧示例(请参阅tinyurl.com/reproducible-000),那么我们可以解释正在发生的事情......
【解决方案2】:

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

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

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

然而,这并不能解释发生了什么。

(编辑:Matthew Lundberg 指出我需要使用 pmin 让它与矢量化输入一起工作。这解决了让它工作的问题,但我仍然不确定它为什么舍入不正确。)

【讨论】:

  • pmin 是矢量化的min 函数。
  • Pmin 至少解决了这个问题。谢谢。
  • 如果你去半个地球,你可能也需要pmax。 acos(pmax(pmin(..., 1)-1)) -- Ben 刚刚添加到他的答案中。
  • 如果他们用 1 分钟的时间来控制这种距离,我们会遇到比算术错误更大的问题 - 但谢谢!
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
相关资源
最近更新 更多