2つの緯度経度ポイント間の距離を計算するときに、余弦よりも余弦の法則の方が望ましいのはなぜですか?


41

実際、SinnottがHaversine式を公開したとき、計算精度は制限されていました。現在、JavaScript(および最新のコンピューターと言語のほとんど)はIEEE 754 64ビット浮動小数点数を使用しており、15桁の精度を実現しています。この精度により、余弦公式の単純な 球面法則cos c = cos a cos b + sin a sin b cos C)により、約1メートルの距離まで良好な条件の結果が得られます。 これを考慮すると、ほとんどの場合、単純なコサインの法則、またはHaversineよりもより正確な楕円形のVincenty式を使用する価値があります。(球体モデルの精度の制限に関する以下の注意事項に留意してください)。
ソース:http : //www.movable-type.co.uk/scripts/latlong.html

余弦の法則がより望ましい理由は何ですか?

注:引用されたテキストは、によって更新されたその作者に述べたように下回ります


10
余弦の法則はどのように「望ましい」のですか?これには、コンピューターとプログラマーの2つの方法で答えることができます。コンピューターの場合、haversine数式は、使用するトリガー関数の数は少なくなりますが、2つの平方根が必要です。計算効率を上げるためには、それはあきらめです。プログラマーにとって、haversineの式はもう少し長くなります。ただし、余弦の法則では、ACos実装が必要です。これは、ATan実装よりもやや少ない頻度で見られます。さらに、防弾コードを作成するには、ACosが失敗しないことを確認する必要があります。この理由だけでも、ハベルシンを好むべきです。
whuber

2
PythonでHaversineとcosineを実装しました。このコンピューターでは、haversineは3.3μsを、cosineは2.2μsを要します。これは、多くを行う必要がある場合に非常に重要です
ニブラー

1
良い観察と情報を提供してくれたすべての人に感謝します。質問で引用されているテキストを更新し、より客観的で役立つように願っています。
ChrisV

@ChrisV、アップデートをありがとう!これは、質問に対する直接的な回答ではないため、コメントに移動しました。すばらしいサイトをありがとう。
scw

回答:


48

問題は「条件の整った」という言葉で示されます。これは数学ではなく、コンピューターの算術の問題です。

考慮すべき基本的な事実は次のとおりです。

  1. 地球上の1ラジアンはほぼ10 ^ 7メートルに及びます。

  2. 0に近い引数xの余弦関数は、1- x ^ 2/2にほぼ等しくなります。

  3. 倍精度浮動小数点の精度は約15桁です。

ポイント(2)および(3)は、xが約1メートルまたは10 ^ -7ラジアン(ポイント1)の場合、ほとんどすべての精度が失われることを意味します。1-(10 ^ -7)^ 2 = 1-10 ^- 14は15桁の有効数字のうち最初の14桁がすべてキャンセルされ、結果を表すために1桁だけが残る計算です。これを反転させる(これは逆コサイン「acos」が行うことです)ということは、メートル長距離に対応する角度のacoを計算することは意味のある正確さではできないことを意味します。 (特定の悪いケースでは、精度が失われるとacosが定義されていない値が得られるため、コードが壊れて無回答、無意味な回答、またはマシンがクラッシュします。)同様の考慮事項は、逆余弦の使用を避けることを示唆しています精度の低下に応じて、数百メートル未満の距離が関係する場合。

単純な余弦の法則でacosが果たす役割は、角度を距離に変換することです。その役割は、haversineフォーミュラでatan2が果たします。小さな角度xの接線は、x自体にほぼ等しくなります。したがって、ほぼその数値である数値の逆正接は、本質的に精度を損なうことなく計算されます。ハーベシン式は、余弦式の法則と数学的に同等ですが、短い距離(1メートル以下)ではるかに優れているのはこのためです。

地球上で100個のランダムなポイントペアを使用した2つの式の比較です(Mathematicaの倍精度計算を使用)。

代替テキスト

約0.5メートル未満の距離では、2つの式が異なることがわかります。0.5メートルを超えると、彼らは同意する傾向があります。次のプロットは、それらがどの程度一致しているかを示すために、緯度と経度が最大5メートルまでランダムに異なる、別の100のランダムポイントペアの余弦法則の結果を示しています。

代替テキスト

これは、距離が5〜10メートルを超えると、余弦の法則が小数点以下3〜4桁になることを示しています。精度の小数点以下の桁数は二次的に増加します。したがって、50〜100メートル(1桁)で5〜6 dpの精度(2桁)が得られます。500-1000メートルでは7-8 dpなどが得られます。


安価なテストがありdelta latitude > .1 || delta longitude > .1ますか?たとえば、コサイン(大きい場合)またはハバーシン(短い距離の場合)を動的に選択しますか?最高のパフォーマンスと精度を得るために。
アノニムース

@ Anony-Mousse両方の式は、世界の4分の1の距離で1/10の数パーセントずれている可能性があるため、それまでに精度に困惑することはありません!したがって、近い点(数百メートル)をほぼすべての正反対の点(約2,000万メートル)とその間のすべてから区別できるテストであれば十分です。
whuber

DOESは、atan2以上の数値の利点を提供しますかasin?ベンチマークを見ましたが、ここでatan2はの2〜3倍遅くasin、2番目sqrtも必要です。
エーリッヒシューベルト

@Erich私は違いを研究していませんが、それasinは本質的に同じことでacosあり、したがって特定の値、この場合は1と-1に近い引数に対して同じ精度の損失に苦しんでいることに注意してください。原則として、atan2その問題はありません。
whuber

それは非常に長い距離にありますか?それを上記の@ Anony-Mousseの提案と組み合わせると、興味深いように思えます。
エーリッヒシューベルト

6

歴史的な脚注:

Haversineは、次のような計算における大きな丸め誤差を回避する方法でした

1 - cos(x)

xが小さい場合。Haversineに関しては、

1 - cos(x) = 2*sin(x/2)^2
           = 2*haversin(x)

および2 * sin(x / 2)^ 2は、xが小さい場合でも正確に計算できます。

昔、haversineフォーミュラには、追加(アンチログルックアップ、追加、およびログルックアップを伴う)を回避するという追加の利点がありました。乗算のみを伴う三角関数式は、「対数形式」であると言われていました。

最近では、haversineフォーミュラの使用は少し時代遅れです。角度xは、項sin(x)で表される場合がありますcos(x)(およびxは明示的に認識されない場合があります)。その場合、1 - cos(x)haversine公式を介した計算には、アークタンジェント(角度xを取得する)、半分(取得するx/2)、サイン(取得するsin(x/2))、正方形(取得するsin(x/2)^2)、および最終的な倍増が必要です。評価を使用する方がはるかに良い

1 - cos(x) = sin(x)^2/(1 + cos(x))

三角関数の評価を必要としません。(明らかに、右側を使用するのはcos(x) > 0;の場合のみで、そうでない場合は、1 - cos(x)直接使用しても構い ません。)


1

コサイン式は1行で実装できます。

  Distance = acos(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(lon2-lon1))*6371

Haversine式は複数の行を取ります:

  dLat = (lat2-lat1)
  dLon = (lon2-lon1)
  a = sin(dLat/2) * sin(dLat/2) + cos(lat1) * cos(lat2) * sin(dLon/2) * sin(dLon/2)
  distance = 6371 * 2 * atan2(sqrt(a), sqrt(1-a))

数学的には同一であるため、唯一の違いは実用性です。


元のHaversineはコンピューター関連のatan2数式を使用していませんが、上記の4行を1つの数式に書き換えることを妨げるものは何もありません。
アルジャン

@ Arjan、True。ただし 2回計算する必要があるため非効率です。数式にはSqrt(a)とSqrt(1-a)の両方が含まれていることが不可欠です。これらの一方は非常に短い距離または非常に長い距離では数値的に不安定になりますが、もう一方はそうではないためです。
whuber

確かに、@ whuberですが、行数が多いために、どちらかを選択することになるとは思いません。(そして、あなたがあなたの答えですでに説明されいるようにそれを支持するはるかに重要な理由があります。)
アルジャン

3
@Arjan同意します。最優先事項は、プログラミングタスクのコードが適切であることです。その後、明快さ、つまり、読みやすさ、保守性、および読み書き可能なドキュメントを配置します。このようなコンテキストがない場合、コードの行数を数えることは無意味です。
whuber

1
atan2(sqrt(a), sqrt(1-a))と同じですasin(sqrt(a))
user102008
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.