用 Python 计算两点距离:坐标签到的输入校验与边界

举报
yd_243677465 发表于 2026/11/14 13:21:17 2026/11/14
【摘要】 阅读鸿蒙开发实践中心的“使用 Agent 生成鸿蒙端云一体员工签到 App”案例时,我注意到一个容易忽略的环节:位置签到最终要把两个经纬度转换成距离,再与允许半径比较。本文用 Python 标准库单独实现一个球面距离示例,帮助理解这一步的边界;这不是对原案例后端实现的复现,也没有部署该案例。 先明确输入与单位经度范围是 -180 到 180 度,纬度范围是 -90 到 90 度。函数返回距离...

阅读鸿蒙开发实践中心的“使用 Agent 生成鸿蒙端云一体员工签到 App”案例时,我注意到一个容易忽略的环节:位置签到最终要把两个经纬度转换成距离,再与允许半径比较。本文用 Python 标准库单独实现一个球面距离示例,帮助理解这一步的边界;这不是对原案例后端实现的复现,也没有部署该案例。

先明确输入与单位

经度范围是 -180 到 180 度,纬度范围是 -90 到 90 度。函数返回距离,单位是米。球面模型把地球简化为半径约 6371 千米的球体,适合教学和粗略距离估计;精确测量需要考虑地球椭球模型、坐标系和设备精度。

一个可运行的距离函数

下面的实现使用 Haversine 公式。先验证输入为有限数值,再将角度转为弧度,最后计算球面大圆距离。对中间变量夹在 0 到 1 的范围内,是为了避免浮点舍入让平方根或反三角函数遇到越界值。

from math import asin, cos, isfinite, radians, sin, sqrt

EARTH_RADIUS_M = 6_371_000

def distance_m(lat1, lon1, lat2, lon2):
    coordinates = (lat1, lon1, lat2, lon2)
    if not all(isinstance(v, (int, float)) and not isinstance(v, bool) and isfinite(v) for v in coordinates):
        raise ValueError("coordinates must be finite numbers")
    if not (-90 <= lat1 <= 90 and -90 <= lat2 <= 90 and -180 <= lon1 <= 180 and -180 <= lon2 <= 180):
        raise ValueError("latitude or longitude out of range")
    a1, a2 = radians(lat1), radians(lat2)
    dlat, dlon = radians(lat2 - lat1), radians(lon2 - lon1)
    a = sin(dlat / 2) ** 2 + cos(a1) * cos(a2) * sin(dlon / 2) ** 2
    return 2 * EARTH_RADIUS_M * asin(sqrt(min(1.0, max(0.0, a))))

做几个小检查

相同坐标的距离应为 0;赤道附近纬度相差 1 度约为 111 千米;交换起点与终点,距离应相同;无效纬度与 NaN 应被拒绝。本地运行这五项断言均通过。示例不依赖网络,也不采集任何人的位置。

把这个函数用于签到逻辑时,还要单独校验半径为非负有限数,并约定边界点(例如距离等于半径时)如何处理。设备定位存在误差,不能把计算出的米数当成绝对精度;实际业务应记录定位时间和精度,必要时给用户重新定位或人工复核的途径。身份鉴权、定位数据最小化和安全传输也需要在完整系统中处理。

参考阅读:华为云鸿蒙开发实践中心《使用 Agent 生成鸿蒙端云一体员工签到 App》。本文代码为独立的小型演示。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。