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

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

提问人:David Manheim 提问时间:12/25/2012 最后编辑:Praveen Kumar PurushothamanDavid Manheim 更新时间:4/8/2022 访问量:11797

问:

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

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

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

浮点 精度 R-FAQ

评论

0赞 David Manheim 12/25/2012
该函数适用于向量;例如,我会使用 dist(lat(1:5), long(1:5),lat(2:6), long(2:6)) 作为输入,其中函数 dist(lat1, long1, lat2, long2)。
0赞 Eric Postpischil 12/25/2012
请参阅此问题此问题维基百科
1赞 David Manheim 1/16/2013
@EricPostpischil 语言不同,并且没有提供在 R 中工作的解决方案。

答:

1赞 David Manheim 12/25/2012 #1

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

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

现在,它确保精度损失导致的值不正好大于 1。

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

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

评论

2赞 Matthew Lundberg 12/25/2012
pmin是矢量化函数。min
0赞 David Manheim 12/25/2012
至少 Pmin 解决了这个问题。谢谢。
2赞 Matthew Lundberg 12/25/2012
如果你去半个地球,你可能也需要去那里。 ——这是本刚刚添加到他的回答中的。pmaxacos(pmax(pmin(..., 1)-1))
2赞 David Manheim 12/25/2012
如果他们用 1 分钟的刻度来管理这种距离,我们就会遇到比算术错误更大的问题 - 但谢谢!
9赞 Ben Bolker 12/25/2012 #2

如果不查看您的数据,就无法准确判断(尝试),但这很可能是常见问题解答 7.31 的结果。dput

(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))

评论

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

我刚刚遇到了这个。这是由大于 1 的输入引起的。由于计算错误,单位范数之间的内积变得比 1 大一点(比如 1+0.00001)。并且只能处理 [-1,1]。因此,我们可以将上限精确到 1 来解决问题。acos()

对于 numpy:np.clip(your_input, -1, 1)

对于 Pytorch:torch.clamp(your_input, -1, 1)

评论

0赞 Ben Bolker 4/8/2022
有点跑题了,因为原始帖子被标记为 [r],但它大概会很有用,所以我不会投反对票......