You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SymPy求解Haversine公式坐标分量时程序挂起问题

我碰到过类似的问题,SymPy的符号求解在处理这种带三角函数的超越方程时确实容易卡壳,原因和解决方法我给你梳理一下:

问题分析:为什么SymPy的solve()会挂起?

你尝试求解的是一个超越方程(包含三角函数与未知变量的混合表达式),SymPy的solve()函数主打寻找解析解,但这类方程通常没有闭合形式的解析解,SymPy会陷入复杂的符号推导循环,最终导致超时或无限挂起。

最优解决方案:利用方向特殊性简化公式

因为你要计算的是正北/正南/正东/正西四个特殊方向的点,完全可以简化Haversine公式,直接用数值计算得到结果,比符号求解高效得多:

1. 正北/正南方向(经度不变)

当两点在同一条经线上时,Haversine公式可以简化为:

球面距离 = 地球半径 × 纬度差(弧度)

推导后,纬度差的弧度值为 Δlat_rad = 距离 / 地球半径,转换为度数后直接加减到中心纬度即可。

2. 正东/正西方向(纬度不变)

当两点在同一条纬线上时,Haversine公式简化后可以解出经度差:

sin(Δlon/2) = sin(距离/(2×地球半径)) / cos(中心纬度弧度)

计算出经度差的弧度值后,加减到中心经度即可。

代码实现(用Python标准库math)

import math

# 定义参数
EARTH_RADIUS_MILES = 3950.0
center_lat = 38.0
center_lon = -77.0
target_distance = 5.0

# 计算正北点
delta_lat_rad = target_distance / EARTH_RADIUS_MILES
north_lat = center_lat + math.degrees(delta_lat_rad)
north_point = (round(north_lat, 6), center_lon)

# 计算正南点
south_lat = center_lat - math.degrees(delta_lat_rad)
south_point = (round(south_lat, 6), center_lon)

# 计算正东点
center_lat_rad = math.radians(center_lat)
sin_half_dlon = math.sin(target_distance / (2 * EARTH_RADIUS_MILES)) / math.cos(center_lat_rad)
delta_lon_rad = 2 * math.asin(sin_half_dlon)
east_lon = center_lon + math.degrees(delta_lon_rad)
east_point = (center_lat, round(east_lon, 6))

# 计算正西点
west_lon = center_lon - math.degrees(delta_lon_rad)
west_point = (center_lat, round(west_lon, 6))

# 输出结果
print(f"正北点: {north_point}")
print(f"正南点: {south_point}")
print(f"正东点: {east_point}")
print(f"正西点: {west_point}")
如果一定要用SymPy:改用数值求解

如果你坚持要用SymPy,可以放弃solve()(找解析解),改用nsolve()进行数值求解,它会通过迭代快速找到近似解,不会挂起:

import sympy as s

lat1 = s.rad(38.0)
lat2 = s.Symbol('lat2')
lon1 = s.rad(-77.0)
lon2 = s.rad(-77.0)
d = 5.0
R = 3950.0

dlon = lon2 - lon1
dlat = lat2 - lat1
a = (s.sin(dlat/2))**2 + s.cos(lat1) * s.cos(lat2) * (s.sin(dlon/2))**2
c = 2 * s.atan2(s.sqrt(a), s.sqrt(1-a))
eq = R * c - d

# 用nsolve,传入初始猜测值(比如中心纬度38.0)
lat2_sol_deg = s.deg(s.nsolve(eq, lat2, 38.0))
print(f"正北点纬度: {round(lat2_sol_deg, 6)}")

这个方法同样适用于其他方向的求解,只需要调整符号变量(比如求解正东点时固定纬度,设经度为变量)和初始猜测值即可。

内容的提问来源于stack exchange,提问作者Brad Solomon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:12:28