两种高效计算 两个经纬度之间距离的方法--解决Haversine 公式性能慢的问题

目录

前言    

Haversine

原理

实现代码

优化后的距离计算

原理

代码

性能及精度对比


前言    

 最新开发的业务中,涉及到计算两个经纬度之间的距离。已知A点和B点的 经纬度,计算A点到B点之间的距离。最开始使用的是Haversine公式来进行计算,但上线后出现严重的性能问题,主要原因是业务数据量太大,每天PB级的数据量。

因此,需要研究一个更高效便捷的计算方法,下面将介绍Haversine公式和实现代码,以及新的计算公式&代码,并对他们的性能及精度进行分析。

Haversine

原理

Haversine 公式是一种用于计算球面上两个坐标点之间距离的数学公式,特别适用于地球上的球面距离计算。该公式基于球面三角学,利用球面上两点间的弧长来计算它们之间的距离。这个公式的形式如下:

总的来说,Haversine 公式通过计算球面上两点间的弧长,提供了一种相对精确的球面距离计算方法。这种方法在小球面(如地球)上非常常见,并在航海、导航等领域广泛应用。

实现代码

public class DistanceCalculator {// 地球半径,单位为千米private static final double EARTH_RADIUS = 6371.0;// 将角度转换为弧度private static double toRadians(double degree) {return degree * Math.PI / 180.0;}// 计算两个经纬度之间的距离,返回结果单位为千米public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {double dLat = toRadians(lat2 - lat1);double dLon = toRadians(lon2 - lon1);double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *Math.sin(dLon / 2) * Math.sin(dLon / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));return EARTH_RADIUS * c;}public static void main(String[] args) {// 示例坐标:纬度 Latitude 1: 40.748817, 经度 Longitude 1: -73.985428// 示例坐标:纬度 Latitude 2: 34.052235, 经度 Longitude 2: -118.243683double distance = calculateDistance(40.748817, -73.985428, 34.052235, -118.243683);System.out.println("Distance between the two coordinates: " + distance + " km");}
}

如果对计算性能不是特别严苛,可以优先使用Haversine 公式来进行计算。但是对于TB级或者PB量级的数据业务来说,这个公式由于计算过于复杂,存在比较大的性能问题。

通过火焰图分析,主要是Math.atan2() 函数的计算开销比较大。

优化后的距离计算

原理

使用弧度计算的简单直线距离计算公式:

由于地球的半径很大,在一个很小的区域内(公里级)可以近似成一个平面,这里直接采用勾股定理来计算直线距离。虽然精度可能会略有降低,但是由于计算公式很简单,性能会有极大提升。

代码

public class SimpleDistanceCalculator {// 将角度转换为弧度private static double toRadians(double degree) {return degree * Math.PI / 180.0;}// 计算两个经纬度之间的简易直线距离,返回结果单位为千米public static double calculateSimpleDistance(double lat1, double lon1, double lat2, double lon2) {double dLat = toRadians(lat2 - lat1);double dLon = toRadians(lon2 - lon1);// 使用简化的直线距离公式double distance = Math.sqrt(dLat * dLat + dLon * dLon) * 60 * 1.852;return distance;}public static void main(String[] args) {// 示例坐标:纬度 Latitude 1: 40.748817, 经度 Longitude 1: -73.985428// 示例坐标:纬度 Latitude 2: 34.052235, 经度 Longitude 2: -118.243683double simpleDistance = calculateSimpleDistance(40.748817, -73.985428, 34.052235, -118.243683);System.out.println("Simple distance between the two coordinates: " + simpleDistance + " km");}
}

性能及精度对比

前者计算1千万次使用的时间为:4462ms

优化后计算1千万次使用的时间为:244ms

优化后耗时为原来的 5.4%。

精度上,在短距离(例如 5 公里以内),Haversine 公式和等矩形投影(简化后的方法)之间的精度差异可能不会很大。在这个范围内,球面和平面的差异相对较小,因此简化的方法通常能够提供足够的精度。

然而,具体的精度差异会受到多个因素的影响,包括具体的坐标位置、所使用的地球半径,以及计算时是否考虑了地球的椭球形状等。因此,很难给出一个具体的数字来表示它们之间的精度差异。

为了获取更准确的精度比较,最好的方法是使用实际的测试数据,并比较两种方法得到的结果。你可以选择一些已知距离的坐标点,分别使用 Haversine 公式和等矩形投影计算它们之间的距离,然后比较计算结果。

本人的一个实际路测,在5公里范围内,大约存在5%到15% 之间的差异。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ResNet论文阅读和简单实现

论文:https://arxiv.org/pdf/1512.03385.pdf Deep Residual Learning for Image Recognition 本模块主要是阅读论文,会做简单的翻译(至少满足我自己能看明白)。 Introduction 由上图可见,在20层和56层的网络上训练的…

听GPT 讲Rust源代码--compiler(11)

File: rust/compiler/rustc_mir_transform/src/simplify.rs 在Rust源代码中,rust/compiler/rustc_mir_transform/src/simplify.rs文件是Rust编译器中一系列进行MIR(中间表示)简化的转换的实现。MIR是Rust编译器中用于进行优化和代码生成的中间…

基于Vue的宿舍管理系统

基于Vue的宿舍管理系统资源-CSDN文库 基于 Koa 以及 VueJS 的宿舍管理系统。 新增功能: 【楼层管理】添加『入住人员信息』模块,显示入住学生、性别、院系、专业的人数,可用饼图表示【用户信息】学生用户添加性别、院系、专业字段【楼层管理…

VM安装虚拟机及初始化操作

一、VM下载及暗转 虚拟机指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统,在实体计算机中能够完成的工作在虚拟机中都能够实现。VMware 是一款功能强大的桌面虚拟计算机软件,提供用户可在单一的桌面上同时运行不同的…

DataFrame基本操作

目录 一、 创建Dataframe创建空的Dataframe根据列数据创建根据行数据创建根据一个已存在的Dataframe复制一个新的Dataframe(仅包含结构) 一、 创建Dataframe 创建空的Dataframe # 创建一个空的DataFrame df pd.DataFrame(columns[列1, 列2, 列3])# …

Python正则表达式急速入门~正则居然这么容易掌握!

正则表达式在程序开发中会经常用到,比如数据(格式)验证、替换字符内容以及提取字符串内容等等情况都会用到,但是目前许多开发人员对于正则表达式只是处于了解或者是基本会用的阶段。一旦遇到大批量使用正则表达式的情况&#xff0…

腾讯云2024年优惠券领取入口及使用教程

腾讯云作为国内领先的云计算服务提供商,一直致力于为用户提供优质、高效、安全可靠的云计算服务。为了回馈广大用户,腾讯云会不定期地推出各种优惠活动,其中最受欢迎的就是优惠券活动。本文将详细介绍腾讯云优惠券的领取入口及使用教程。 一、…

bat批处理文件_命令汇总(1)

文章目录 1、复制文件:2、 移动文件:3、删除文件:4、创建目录:5、删除目录:6、切换目录:7、显示当前目录:8、运行程序:9、显示系统环境变量:10、设置环境变量&#xff1a…

LeetCode---378周赛

题目列表 2980. 检查按位或是否存在尾随零 2981. 找出出现至少三次的最长特殊子字符串 I 2982. 找出出现至少三次的最长特殊子字符串 II 2983. 回文串重新排列查询 一、检查按位或是否存在尾随零 这题和位运算有关,不是很难,题目要求至少有两个数的…

Hadoop集群三节点搭建(一)

一、第一台虚拟机准备 确认是可以上网,方便下载文件和工具,使用ping命令测试下 安装工具 net-tool:工具包集合,包含ifconfig等命令,大家可以根据自己需要按需下载 创建普通用户attest,并修改attest用户的密…

ubuntu18.04查询实时内存、CPU占用率命令

gnome-system-monitor效果就是下面这样:

C语言快速入门——基础知识

C语言基础 C语言基础C程序基本格式基本数据类型原码、反码和补码原码反码补码 整数类型浮点类型字符类型 变量变量的使用无符号数类型转换 运算符基本运算符运算符优先级自增自减运算符位运算符逻辑运算符 流程控制分支语句 - if分支语句 - switch循环语句 - for循环语句 - whi…