緯度/経度 (ラジアンではなく度数) とコサインの球面法則を使用して 2 点の距離を計算する関数を作成しています。私が抱えている問題は、関数の丸め誤差のためacos()
に、2 つの点が互いに非常に近い場合に得られる結果があまり良くないことです。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct{
double lat;
double lon;
} point;
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define EARTH_RADIUS_IN_METERS 6372797.560856
double distance(point a, point b) {
double arg=sin(a.lat * DEG_TO_RAD) * sin(b.lat * DEG_TO_RAD) + cos(a.lat * DEG_TO_RAD) * cos(b.lat * DEG_TO_RAD) * cos((a.lon-b.lon) * DEG_TO_RAD);
if(arg>1) arg=1;
else if (arg<-1) arg=-1;
printf("arg=%.12f acos(arg)=%.12f\n",arg, acos(arg)); //to see the problem
return acos(arg) * EARTH_RADIUS_IN_METERS;
}
int main(){
point p1,p2;
p1.lat=63.0;
p1.lon=27.0;
p2.lat=p1.lat;
p2.lon=p1.lon;
printf("dist=%.8f\n",distance(p1,p2));
return 0;
}
出力は
arg=1.000000000000 acos(arg)=0.000000014901
dist=0.09496208
ご覧のとおり、計算するacos()
とゼロになるはずですが、地球の半径を掛けた後に非常に拡大されるいくつかのエラーが発生します。また、2 つの点が等しくないが非常に近い場合にも発生します。緯度と経度に関する私のデータは、10 進数で 7 桁までです。