作为算法领域的研究者,我会从用途、核心原理、前置知识、公式拆解、代码实现 五个维度,给你讲清楚 Haversine 距离算法 ------ 它是计算地球表面两点球面直线距离的经典算法,日常用的地图测距、打车软件预估里程,背后都有它的身影。
一、 算法的核心用途
我们生活的地球是一个近似球体,如果要计算两个地点(比如北京到上海)的 "直线距离",不能直接用平面几何的勾股定理(因为地球表面是曲面)。
Haversine 算法的作用,就是基于两点的经纬度坐标,计算它们在地球球面上的最短距离 (这个最短距离也叫大圆距离,即穿过球心的平面切割球面形成的圆弧长度)。
二、 必须掌握的前置知识
在理解公式前,先记住 3 个关键概念:
- 经纬度的定义
- 纬度 (latitude) :衡量地点南北位置,范围是
[-90°, 90°],赤道是 0°,北极是 90°N,南极是 90°S。 - 经度 (longitude) :衡量地点东西位置,范围是
[-180°, 180°],本初子午线是 0°,向东为东经,向西为西经。
- 纬度 (latitude) :衡量地点南北位置,范围是
- 角度与弧度的转换 数学中三角函数(sin、cos)的计算需要弧度值 ,而我们日常用的经纬度是角度值 ,因此必须先转换:
- 弧度 = 角度 × π / 180°
- 角度 = 弧度 × 180° / π
- 地球半径的取值 地球不是完美球体,赤道半径约 6378km,极半径约 6357km。日常计算取平均半径 R = 6371km 即可满足精度需求。
三、 Haversine 公式拆解
1. 公式的数学表达式
假设地球表面有两点:
- 点 A:纬度
lat1,经度lon1 - 点 B:纬度
lat2,经度lon2
Haversine 公式的最终形式为:
d=2R⋅arcsin(sin2(2Δlat)+cos(lat1)⋅cos(lat2)⋅sin2(2Δlon))
其中:
- Δlat=lat2−lat1 :两点的纬度差
- Δlon=lon2−lon1 :两点的经度差
- R :地球平均半径(6371km)
- d :两点的球面直线距离
2. 公式的通俗理解(分 4 步计算)
我们不用死记公式,而是把计算拆成 4 个简单步骤:
- 角度转弧度 将
lat1, lon1, lat2, lon2全部转换成弧度值(记为φ1, λ1, φ2, λ2)。 - 计算差值计算纬度差 Δφ=φ2−φ1,经度差 Δλ=λ2−λ1。
- 计算核心根式代入公式计算根号内的部分:a=sin2(2Δφ)+cos(φ1)⋅cos(φ2)⋅sin2(2Δλ)
- 计算最终距离代入公式计算距离:d=2R⋅arcsin(a)
四、 零基础能看懂的 Python 代码实现
下面给出完整的 Python 代码,逐行添加中文注释,你可以直接复制运行。我们以 ** 北京(39.9042°N, 116.4074°E)到上海(31.2304°N, 121.4737°E)** 为例计算距离。
python
运行
# 导入数学库,用于三角函数和弧度转换
import math
def haversine_distance(lat1, lon1, lat2, lon2):
"""
计算地球表面两点的球面直线距离
参数:
lat1: 点1的纬度(角度值)
lon1: 点1的经度(角度值)
lat2: 点2的纬度(角度值)
lon2: 点2的经度(角度值)
返回:
distance: 两点的球面距离,单位为千米(km)
"""
# 步骤1:定义地球平均半径(单位:km)
R = 6371.0
# 步骤2:将角度值转换为弧度值
phi1 = math.radians(lat1) # 点1纬度弧度
lambda1 = math.radians(lon1)# 点1经度弧度
phi2 = math.radians(lat2) # 点2纬度弧度
lambda2 = math.radians(lon2)# 点2经度弧度
# 步骤3:计算纬度差和经度差的弧度值
delta_phi = phi2 - phi1
delta_lambda = lambda2 - lambda1
# 步骤4:计算公式中的a值
a = math.sin(delta_phi / 2.0) ** 2 + \
math.cos(phi1) * math.cos(phi2) * \
math.sin(delta_lambda / 2.0) ** 2
# 步骤5:计算最终距离
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) # 等价于2*arcsin(sqrt(a))
distance = R * c
return distance
# 测试:北京到上海的经纬度
beijing_lat, beijing_lon = 39.9042, 116.4074
shanghai_lat, shanghai_lon = 31.2304, 121.4737
# 调用函数计算距离
distance = haversine_distance(beijing_lat, beijing_lon, shanghai_lat, shanghai_lon)
print(f"北京到上海的球面直线距离约为:{distance:.2f} 千米")
代码运行结果
plaintext
北京到上海的球面直线距离约为:1067.99 千米
这个结果和实际地图测距的误差在 1% 以内,完全满足日常使用需求。
五、 算法的优缺点与适用场景
1. 优点
- 计算简单:仅依赖基础三角函数,代码实现成本低。
- 精度足够:对于非高精度场景(如打车、外卖、旅游),误差可忽略。
- 无依赖:不需要额外的地理数据,只要经纬度就能计算。
2. 缺点
- 假设地球是完美球体:实际地球是 "椭球体",在高纬度地区误差会略大(但不超过 0.5%)。
- 不适合超长距离高精度计算 :比如洲际导航,此时建议用更精确的 Vincenty 算法(基于椭球模型)。
3. 典型适用场景
- 地图 APP 的两点测距功能
- 打车 / 外卖软件的预估里程与费用计算
- 物流行业的路径规划(同城 / 省内)
- 户外探险的定位与距离估算
六、 总结
Haversine 距离算法的核心就是把地球当成球体,用球面三角学替代平面几何,实现经纬度到实际距离的转换。对于零基础的学生,只要记住 "角度转弧度→算差值→代入公式→乘地球半径" 这四步,就能轻松掌握这个算法的原理和应用。