Сферический закон косинусов отличается между MySQL и PHP

В нашем приложении мы используем PHP для расчета расстояния между координатами с помощью формулы сферического закона косинусов. Однако это не так хорошо масштабируется, поэтому я переработал код, чтобы вычислить расстояние в MySQL.
Когда я сравниваю результаты расчетов PHP и MySQL, я вижу существенные различия.

Lat       | Lng        | PHP     | MySQL
47.457131 | -10.615383 | 1112.8  | 7604.07
61.265367 | 19.939854  | 1508.5  | 6905.3
56.64524  | -21.312707 | 1745.6  | 8589.3
37.028064 | 18.732122  | 1957.5  | 4954.33
38.823754 | -17.029437 | 2112    | 7856.57
70.687405 | 11.08298   | 2217.1  | 7969.53

Все эти расстояния рассчитываются между этими координатами и (широта: 51.0363432, долгота: 3.7351858).

Вот как это было рассчитано в PHP

public function getDistance($longitude, $latitude)
{
    $pi = pi();
    $dist = (
            (
            acos(
                sin($latitude * $pi / 180)
                *
                sin($this->latitude * $pi / 180)
                +
                cos($latitude * $pi / 180)
                *
                cos($this->latitude * $pi / 180)
                *
                cos(($longitude - $this->longitude) * $pi / 180)
            )
            ) * 180 / $pi
        ) * 60 * 1.1515;

    $metric = $dist / 0.62137;
    return $metric;
}

Вот как это вычисляется в SQL

public static function getDistanceQuery($lat, $lng, $distance_name, $units)
{
    /*
     *  Allow for changing of units of measurement
     */
    switch ($units) {
        case 'mi':
            //radius of the great circle in miles
            $gr_circle_radius = 3959;
            break;
        default:
            //radius of the great circle in kilometers
            $gr_circle_radius = 6371;
            break;

    }

    /*
     *  Generate the select field for distance
     */
    $distance_select = sprintf(
        "ROUND(
            ( %d
                * acos(
                    cos( radians(%s) )
                    * cos( radians( latitude ) )
                    * cos( radians( longitude ) - radians(%s) )
                    + sin( radians(%s) )
                    * sin( radians( latitude ) )
                )
            )
        , 2 )
        AS %s ",
        $gr_circle_radius,
        $lat,
        $lng,
        $lat,
        $distance_name
    );
    return $distance_select;
}

Эти большие различия связаны с более высокой точностью SQL или что-то не так с одним из кодов?


person Swimburger    schedule 03.02.2016    source источник


Ответы (1)


Я нашел проблему, я должен был сделать математику вручную, прежде чем предполагать. Широта и долгота были перевернуты функцией, в которой вызывается код MySQL.
Теперь результаты очень близки друг к другу, с небольшими десятичными различиями.

person Swimburger    schedule 03.02.2016