路线近似距离计算异常:Haversine公式实现问题排查求助
问题排查与修复方案
1. 数据库列名不匹配的潜在问题
你的getPoints方法中存在SQL查询字段与游标获取字段不匹配的问题:
Cursor cursor = db.rawQuery("select latitude,longitude from " + Table_Name_Location, null); // 游标获取时用的是"Lat"和"Longi",与查询的字段名不一致 Double latitude = cursor.getDouble(cursor.getColumnIndex("Lat")); Double longitude = cursor.getDouble(cursor.getColumnIndex("Longi"));
如果数据库表的实际列名是latitude和longitude,getColumnIndex("Lat")会返回-1,调用getDouble(-1)会读取错误值或抛出异常。请根据数据库实际列名修正:
- 若表列名为
Lat、Longi,修改SQL语句为select Lat, Longi from ... - 若表列名为
latitude、longitude,修改游标获取参数为"latitude"和"longitude"
2. Haversine公式的单位转换问题
当前distance方法返回的是英里(* 60 * 1.1515是海里转 statute miles的系数),如果预期结果是公里,需调整单位转换逻辑:
// 转换为公里:1海里 = 1.852公里 dist = dist * 60 * 1.852;
若确实需要英里,此部分无需修改,但单位误解是结果“不正确”的常见原因。
3. Haversine公式的精度优化(可选)
使用acos的实现在两点极近时会有浮点精度问题,建议改用更稳定的半正矢公式:
private double distance(double lat1, double lon1, double lat2, double lon2) { double dLat = deg2rad(lat2 - lat1); double dLon = deg2rad(lon2 - lon1); double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); double dist = 6371 * c; // 地球半径(公里),需英里则替换为3956 return dist; }
4. 路线点遍历逻辑验证
确认调用distance时,正确遍历ArrayList中的相邻点:
ArrayList<Double> points = getPoints(); double totalDistance = 0; // 每次步进2,确保取到相邻的[lat, lon]对 for (int i = 0; i < points.size() - 2; i += 2) { double lat1 = points.get(i); double lon1 = points.get(i+1); double lat2 = points.get(i+2); double lon2 = points.get(i+3); totalDistance += distance(lat1, lon1, lat2, lon2); }
若遍历索引错误(如每次i++),会导致把经度和下一个纬度当作一组点计算,结果完全错误。
内容的提问来源于stack exchange,提问作者Eex1e
相关产品推荐
相关产品推荐

