【发布时间】:2017-01-12 20:02:44
【问题描述】:
在我的previous question 中,我希望根据函数结果加快列表选择。现在,我的瓶颈是函数本身。
这是一个基本的Haversine函数,使用下面的代码:
private static double Haversine(double lat1, double lat2, double lon1, double lon2)
{
const double r = 6371e3; // meters
var dlat = (lat2 - lat1)/2;
var dlon = (lon2 - lon1)/2;
var q = Math.Pow(Math.Sin(dlat), 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Pow(Math.Sin(dlon), 2);
var c = 2 * Math.Atan2(Math.Sqrt(q), Math.Sqrt(1 - q));
var d = r * c;
return d / 1000;
}
那么...为什么需要这么快?问题是我把它称为很多。想想 16,500,000 次以北。
显然,这很多。在我的用例中,我向它传递了它必须从中获取位置数据的对象,然后将纬度和经度转换为弧度,这进一步增加了时间(仅增加了大约 15%)。我不知道对此我能做些什么,但我确实知道,通过将它以弧度(如上)的形式纯粹传递,它需要大约 4.5 秒 - 这是我实现中处理时间的 75% 以上。为 q 和 c 赋值的行似乎占用了最多的时间。
因为它被称为 a lot,所以我希望它有点更快。我对多线程解决方案持开放态度(目前我自己也在研究一个),但考虑到我上一个问题(上面链接)中的用例,实现起来可能有点困难。
【问题讨论】:
-
最好的优化是少调用它...快速查看其他问题表明您需要“最近的 5”或其他东西。这使得这有点像XY question。
-
为什么转换成弧度或从弧度转换会招致如此沉重的惩罚?它实际上只是一个单一的乘法。当然,它是一个浮点运算,但它仍然应该远不及那些三角函数那么昂贵。
-
另外,我正在查看 Wikipedia 上的半正弦公式的定义,并没有提到需要做 Atan 的任何地方。您实际上试图让此方法返回的值是多少?
-
@HenkHolterman 我认为这始终是看待事物的好方法,也是我经常考虑的事情。如果您可以立即看到可以使用改进的东西,我会打开它。与此同时,这是一项昂贵的手术,我想瘦身。
-
@Abion47 这只是我使用的实现。我认为无论有没有都可以做到,无论哪种方式,距离都是一样的。 我正在寻找两个纬度-经度对之间的距离。 将弧度转换为 1650 万次需要大约 1-1.5 秒。实际上,如果我愿意,我可以将所有值存储为弧度,所以认为这不是问题。作为记录,我使用的 Haversine 公式是从这里提取的 movable-type.co.uk/scripts/latlong.html
标签: c# math optimization trigonometry