PHP returning NaN

岁酱吖の 提交于 2019-11-28 13:13:58

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.

The range of sin() and cos() is between -1 and 1. Therefore in your first calculation of $dist the 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.

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

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

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

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.

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:

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!