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

使用Haversine公式计算用户距离时PostgreSQL报输入超出范围错误

问题原因

PostgreSQL的acos()函数要求输入值必须在[-1, 1]范围内,但由于浮点计算的精度误差,你的Haversine公式计算出的参数可能会出现极小的超出范围值(比如1.0000000001或-1.0000000001),触发"Input is out of range"错误。

解决方案

1. 限制acos参数的取值范围

用PostgreSQL的least()和greatest()函数把计算结果钳制在[-1, 1]之间,修改你的Haversine公式:

String HAVERSINE_FORMULA = "(6371 * acos(least(greatest(cos(radians(?2)) * cos(radians(uwc.latitude)) *" +
    " cos(radians(uwc.longitude) - radians(?1)) + sin(radians(?2)) * sin(radians(uwc.latitude)), -1.0), 1.0)))";

2. 避免重复计算公式(优化性能)

原查询中WHERE和ORDER BY都重复计算了Haversine公式,不仅低效,还可能重复触发精度问题。可以用子查询先计算距离,再过滤排序:

@Query("SELECT uwc FROM (" +
        "SELECT uwc, " + HAVERSINE_FORMULA + " AS distance " +
        "FROM UserWithCoordinate uwc) AS sub " +
        "WHERE sub.distance < ?3 " +
        "ORDER BY sub.distance DESC")
List<UserWithCoordinate> findByCoordinates(double longitude, double latitude, double distance, Pageable pageable);

3. 校验经纬度数据合法性

检查你的UserWithCoordinate表中,latitude是否在[-90, 90]之间,longitude是否在[-180, 180]之间。非法的经纬度值也会导致三角函数计算出异常值。

验证修改

修改后重新测试查询,精度误差被钳制后,acos()函数就不会再抛出越界错误,同时查询性能也会因为避免重复计算而提升。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:03:21