2012-01-02 248 views
-1

我有一個函數可以計算兩個GPS座標之間的距離。然後我得到數據庫中的所有座標,並循環遍歷它們以獲得當前和前一個之間的距離,然後將其添加到特定GPS設備的數組中。由於某種原因,它返回NaN。我曾嘗試將它轉換爲double,int和四捨五入的數字。PHP返回NaN

這是我的PHP代碼:

function distance($lat1, $lon1, $lat2, $lon2) { 
     $lat1 = round($lat1, 3); 
     $lon1 = round($lon1, 3); 
     $lat2 = round($lat2, 3); 
     $lon2 = round($lon2, 3); 
     $theta = $lon1 - $lon2; 
     $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
     $dist = acos($dist); 
     $dist = rad2deg($dist); 
     $miles = $dist * 60 * 1.1515; 
     if($miles < 0) $miles = $miles * -1; 
     return ($miles * 1.609344); 
} 
$this->db->query("SELECT * FROM `gps_loc` WHERE `imeiN`='" . $sql . "' AND `updatetime`>=$timeLimit ORDER BY `_id` DESC"); 
    $dist = array(); 
    $dist2 = array(); 
    while($row = $this->db->getResults()) { 
     $dist2[$row['imeiN']] = 0; 
     $dist[$row['imeiN']][]["lat"] = $row['lat']; 
     $dist[$row['imeiN']][count($dist[$row['imeiN']]) - 1]["lng"] = $row['lon']; 
    } 

    foreach($dist as $key=>$d) { 
     $a = 0; 
     $b = 0; 
     foreach($dist[$key] as $n) { 
      if($a > 0) { 
       $dist2[$key] += $this->distance($n['lat'], $n['lng'], $dist[$key][$a - 1]['lat'], $dist[$key][$a - 1]['lng']); 
      } 
      $a++; 
     } 

    } 
    echo json_encode($dist2); 
+2

你能更詳細地顯示出什麼時候出現錯誤嗎? – 2012-01-02 01:28:42

+0

你確定你從數據庫中得到的值是數字而不是字符串嗎? – Chad 2012-01-02 01:30:29

+0

我建議在距離()公式的每個階段加入調試輸出,準確地確定在哪裏生成nan。 – 2012-01-02 01:34:23

回答

2

您從數據庫中提取的值可能是字符串,這會導致此問題。

您可能還想檢查Kolink在帖子中提出的問題。

4

sin()cos()範圍爲-1到1之間。因此在你的$dist第一個計算結果範圍爲-2到2.然後通過這到acos(),其參數必須在-1和1之間。因此acos(2)例如給出了NaN。從那裏的其他一切都給予了NaN。

我不確定公式應該是什麼,但這就是您的NaN來自哪裏。仔細檢查你的三角。

0

是你使用的餘弦的球形定律嗎?我想切換到haversine公式:

function distance($lat1, $lon1, $lat2, $lon2) 
{ 
    $radius = 3959; //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit 

    $delta_Rad_Lat = deg2rad($lat2 - $lat1); //Latitude delta in radians 
    $delta_Rad_Lon = deg2rad($lon2 - $lon1); //Longitude delta in radians 
    $rad_Lat1 = deg2rad($lat1); //Latitude 1 in radians 
    $rad_Lat2 = deg2rad($lat2); //Latitude 2 in radians 

    $sq_Half_Chord = sin($delta_Rad_Lat/2) * sin($delta_Rad_Lat/2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon/2) * sin($delta_Rad_Lon/2); //Square of half the chord length 
    $ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord)); //Angular distance in radians 
    $distance = $radius * $ang_Dist_Rad; 

    return $distance; 
} 

你應該能夠對地球的半徑從半徑改爲任何形式的測量中光年納米半徑和得到適當數量的背出使用的單位。

4

如果點彼此太接近,算法會產生NaN。在這種情況下,$ dist獲得值1.acos(1)是NaN。所有後續的計算都會產生NaN。 你把第一步的座標作爲圓來處理,所以四捨五入後數值相等的可能性更大,並且產生NaN

+0

不應該acos(1)返回0? http://www.rapidtables.com/math/trigonometry/arccos.htm#table – 2016-02-11 02:31:12

0

感謝這裏的所有答覆 - 因此我做了一個函數,它結合了計算和測試NaN,如果兩者都不是NaN,則計算平均值(如果一個是NaN,另一個不是) - 它使用有效的計算值,並給出計算失敗的座標的錯誤報告:

function distance_slc($lat1, $lon1, $lat2, $lon2) { 
     $earth_radius = 3960.00; # in miles 
     $distance = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon2-$lon1)) ; 
     $distance = acos($distance); 
     $distance = rad2deg($distance); 
     $distance = $distance * 60 * 1.1515; 
     $distance1 = round($distance, 4); 

     // use a second method as well and average   
     $radius = 3959; //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit 
    $delta_Rad_Lat = deg2rad($lat2 - $lat1); //Latitude delta in radians 
    $delta_Rad_Lon = deg2rad($lon2 - $lon1); //Longitude delta in radians 
    $rad_Lat1 = deg2rad($lat1); //Latitude 1 in radians 
    $rad_Lat2 = deg2rad($lat2); //Latitude 2 in radians 

    $sq_Half_Chord = sin($delta_Rad_Lat/2) * sin($delta_Rad_Lat/2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon/2) * sin($delta_Rad_Lon/2); //Square of half the chord length 
    $ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord)); //Angular distance in radians 
    $distance2 = $radius * $ang_Dist_Rad; 
     //echo "distance=$distance and distance2=$distance2\n"; 
    $avg_distance=-1; 
    $distance1=acos(2); 
     if((!is_nan($distance1)) && (!is_nan($distance2))){ 
      $avg_distance=($distance1+$distance2)/2; 
     } else { 
      if(!is_nan($distance1)){ 
       $avg_distance=$distance1; 
       try{ 
        throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2"); 
       } catch(Exception $e){ 
        trigger_error($e->getMessage()); 
        trigger_error($e->getTraceAsString()); 
       } 
      } 
      if(!is_nan($distance2)){ 
       $avg_distance=$distance2; 
       try{ 
        throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2"); 
       } catch(Exception $e){ 
        trigger_error($e->getMessage()); 
        trigger_error($e->getTraceAsString()); 
       } 
      } 
     } 
     return $avg_distance; 
} 

HTH也有人在未來。