PHP 返回 NaN

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8696755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 05:17:49  来源:igfitidea点击:

PHP returning NaN

phpnan

提问by trentr

I have a function that calculates the distance between two GPS coordinates. I then get all the coordinates from the database and loop through them all to get the distance between the current one and the previous one, then add that to an array for the specific GPS device. For some reason it is return NaN. I have tried casting it as a double, an int, and rounding the number.

我有一个计算两个 GPS 坐标之间距离的函数。然后我从数据库中获取所有坐标并遍历它们以获得当前坐标和前一个坐标之间的距离,然后将其添加到特定 GPS 设备的数组中。出于某种原因,它是返回 NaN。我尝试将其转换为双精度型、整数型和四舍五入。

Here is my PHP code:

这是我的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);

回答by Niet the Dark Absol

The range of sin()and cos()is between -1 and 1. Therefore in your first calculation of $distthe result range is -2 to 2. You then pass this to acos(), whose argument must be between -1 and 1. Thus acos(2)for example gives NaN. Everything else from there gives NaN as well.

sin()and的范围cos()介于 -1 和 1 之间。因此,在您第一次计算$dist结果范围时,范围是 -2 到 2。然后将acos()其传递给,其参数必须介于 -1 和 1 之间。因此acos(2),例如给出 NaN。从那里开始的所有其他内容也都给出了 NaN。

I'm not sure what the formula should be exactly, but that's where your NaN is coming from. Double-check your trigonometry.

我不确定公式应该是什么,但这就是您的 NaN 的来源。仔细检查你的三角函数。

回答by Maxim

The algo will produce NaN if points are too close to each other. In that case $dist gets value 1. acos(1) is NaN. All sunsequent calculations produce NaN too. You round coordinates as the first step, so it makes more probable that the values become equal after rounding, and produce NaN

如果点彼此太近,算法将产生 NaN。在这种情况下,$dist 的值为 1。acos(1) 是 NaN。所有后续计算也会产生 NaN。您将坐标舍入作为第一步,因此舍入后值更有可能变得相等,并产生 NaN

回答by Chad

The values you are pulling from the database may be strings, which would cause this issue.

您从数据库中提取的值可能是字符串,这会导致此问题。

You may also want to check the issues that Kolink raised in his post.

您可能还想查看 Kolink 在他的帖子中提出的问题。

回答by Phoenix

Is that the spherical law of cosines you're using? I'd switch to the Haversine formula:

这是您使用的余弦球定律吗?我会切换到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;  
}  

You should be able to change the earth's radius to any form of measurement from radius in light years to radius in nanometers and get the proper number back out for the unit used.

您应该能够将地球半径更改为任何形式的测量形式,从以光年为单位的半径到以纳米为单位的半径,并为所使用的单位获取正确的数字。

回答by Ross

Thanks for all the responses here - as a result I made a function which combines to computations and tests for NaN in each, if both are not NaN - it averages the calculation, if one is NaN and the other is not - it uses the one that's valid and gives error report for the coordinates that failed one of the calculation:

感谢这里的所有回复 - 结果我做了一个函数,它结合了每个 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 someone in the future as well.

HTH 将来也会有人。