地理位置服務(LBS)中常需計算兩點球面距離。本文提供高精度、可配置單位的 PHP 函數,基於 Haversine 公式,假設地球為標準球體。
<?php
/**
* 計算兩組經緯度間的距離
* @param float $lat1 緯度1
* @param float $lng1 經度1
* @param float $lat2 緯度2
* @param float $lng2 經度2
* @param int $unit 1=米(默認) | 2=公里
* @param int $precision 小數位數(默認2)
* @return float 距離
*/
function getDistance($lat1, $lng1, $lat2, $lng2, $unit = 1, $precision = 2) {
$EARTH_RADIUS = 6378.137; // 地球半徑 km
$PI = 3.1415926535898;
$radLat1 = deg2rad($lat1);
$radLat2 = deg2rad($lat2);
$dLat = $radLat1 - $radLat2;
$dLng = deg2rad($lng1) - deg2rad($lng2);
$a = sin($dLat/2)**2 + cos($radLat1) * cos($radLat2) * sin($dLng/2)**2;
$distance = 2 * asin(sqrt($a)) * $EARTH_RADIUS; // km
if ($unit == 1) $distance *= 1000; // 轉米
return round($distance, $precision);
}
// 示例:北京天安門到上海外灘
echo getDistance(39.9042, 116.4074, 31.2304, 121.4737, 2); // 約 1084.56 km
?>
* PI/180,更清晰。round() 避免浮點數顯示雜訊。sin/cos 或使用 MySQL 空間擴展(ST_Distance_Sphere)下推計算。geotools-php/geotools 庫。SELECT ST_Distance_Sphere(
POINT(116.4074, 39.9042),
POINT(121.4737, 31.2304)
) / 1000 AS distance_km;
資料庫層面計算可大幅減少網絡傳輸與 PHP CPU 佔用,推薦大規模 LBS 應用採用。