Unabhängig davon, ob Sie vincenty oder haversine oder das sphärische Gesetz des Cosinus verwenden, ist es ratsam, sich potenzieller Probleme mit dem Code, den Sie verwenden möchten, bewusst zu werden, Dinge zu beachten und abzumildern und wie man mit vincenty vs. haversine vs. sloc-Problemen umgeht werden sich unterscheiden, wenn man sich der lauernden Probleme / Edgecases eines jeden bewusst wird, die im Allgemeinen bekannt sein können oder nicht. Der erfahrene Programmierer weiß das. Neulinge dürfen nicht. Ich hoffe, einige von ihnen vor Frustrationen zu bewahren, wenn ein Ausschnitt aus einem Forum in bestimmten Fällen etwas Unerwartetes bewirkt. Wenn man ernsthaft eine dieser Versionen verwenden möchte, wie zum Beispiel Vincent, Haversine, Sloc, dann haben SE, SO, Reddit, Quora usw. möglicherweise nur eingeschränkte Hilfe bei der anfänglichen Codierung einer Lösung bereitgestellt, aber das bedeutet nicht, dass dies der Fall ist Ihre Lösung oder akzeptierte "Antwort" ist frei von Problemen. Wenn ein Projekt wichtig genug ist, verdient es einen angemessenen Forschungsaufwand. Lesen Sie das Handbuch, lesen Sie die Dokumentation, und falls eine Codeüberprüfung dieses Codes vorliegt, lesen Sie diese. Das Kopieren und Einfügen eines Snippets oder einer Zusammenfassung, das oder die hundertmal oder öfter aktualisiert wurde, bedeutet nicht, dass die Sicherheit umfassend und gewährleistet ist.
Die faszinierende Antwort von cffk macht deutlich, dass es sich bei verpackten Lösungen um lauernde Edgecases handelt, die Ausnahmen oder andere Schwierigkeiten hervorrufen können . Die konkreten Behauptungen, die in diesem Beitrag gemacht werden, übersteigen derzeit mein Zeitbudget, aber ich gehe davon aus, dass in bestimmten Paketen tatsächlich Probleme lauern, einschließlich mindestens einer einzigen Implementierung, für die mindestens eine Person Verbesserungsvorschläge gemacht hat auf die eine oder andere Weise, um das Risiko, auf diese Schwierigkeiten zu stoßen, zu minimieren oder zu beseitigen. Ich werde nicht weiter auf das Thema von Vincent eingehen (da ich es viel zu ignoriert habe), sondern mich stattdessen dem Thema Haversine zuwenden, zumindest teilweise dem Thema mit dem OP.
Die populär veröffentlichte Haversine-Formel, ob in Python oder einer anderen Sprache, da sie wahrscheinlich die IEEE 754-Gleitkomma-Spezifikation für die meisten aktuellen Intel- und Intel-ähnlichen Systeme und ARM-Prozessoren, PowerPCs usw. verwenden wird auch anfällig für seltene, aber reale und wiederholbare Ausnahmefehler in der Nähe oder in einem Bogenabstand von 180 Grad, Antipodenpunkte aufgrund von Gleitkommanäherungen und Abrundungen. Einige Neulinge sind möglicherweise noch nicht von dieser Situation gebissen worden. Da sich diese fp-Spezifikation annähert und rundet, bedeutet dies nicht, dass jeder Code, der fp64 aufruft, Ausnahmefehler verursachen kann, nein. Aber etwas Code, Einige Formeln haben möglicherweise nicht so offensichtliche Randbedingungen, bei denen die Näherungen und Rundungen von IEEE 754 fp64 dazu führen können, dass ein Wert leicht aus dem Bereich einer mathematischen Methode herausfällt, von der erwartet wird, dass sie einen solchen Wert fehlerfrei auswertet. Ein Beispiel ... sqrt (). Wenn ein negativer Wert in ein sqrt () eingeht, z. B. sqrt (-0.00000000000000000122739), liegt ein Ausnahmefehler vor. In der Haversin-Formel gibt es in atan2 () zwei sqrt () -Methoden, um eine Lösung zu finden. Dasa , das in sqrt () berechnet und dann verwendet wird, kann an den Antipodenpunkten auf dem Globus leicht unter 0,0 oder über 1,0 abweichen, sehr leicht aufgrund von fp64-Approximationen und -Rundungen, selten, aber wiederholbar. Die konsistente, zuverlässige Wiederholbarkeit macht dies in diesem Zusammenhang zu einem Ausnahmerisiko, zu einem Edgecase zum Schutz, zur Minderung und nicht zu einem isolierten, zufälligen Zufall. Hier ist ein Beispiel für ein kurzes Python3-Snippet von Haversine ohne den erforderlichen Schutz:
import math as m
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
Sehr nahe oder an antipodalen Punkten, a in der ersten Zeile der Formel berechnetes negativ sein, selten, aber wiederholt mit denselben Lat-Lon-Koordinaten. Zum Schutz / diese seltenen Ereignisse zu korrigieren, kann man einfach hinzufügen, nach dem einer Berechnung, wie unten zu sehen:
import math as m
note = ''
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
if a < 0.0: a = 0.0 ; note = '*'
if a > 1.0: a = 1.0 ; note = '**'
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
# note = '*' # a went below 0.0 and was normalized back to 0.0
# note = '**' # a went above 1.0 and was normalized back to max of 1.0
Natürlich habe ich hier nicht die gesamte Funktion gezeigt, sondern einen kurzen Ausschnitt, wie er so oft gepostet wird. Aber dieses Beispiel zeigt den Schutz für sqrt (), indem es das a testet und es gegebenenfalls normalisiert, wodurch auch die Notwendigkeit vermieden wird, das Ganze mit Ausnahme von "try" zu testen . Das note = '' up top soll verhindern, dass die Bytecode-Stufe gegen die Verwendung dieser Note protestiert, bevor ihr ein Wert zugewiesen wird, wenn sie mit dem Ergebnis der Funktion zurückgegeben wird.
Mit dieser einfachen Änderung des Hinzufügens der beiden a- Tests sind die Funktionen von sqrt () zufriedenstellend, und der Code enthält jetzt eine zusätzliche Notiz , die an den aufrufenden Code zurückgegeben werden kann, um darauf hinzuweisen , dass ein Ergebnis leicht normalisiert wurde, und warum. Einige kümmern sich vielleicht darum, andere kümmern sich vielleicht nicht darum, aber es verhindert einen Ausnahmefehler, der andernfalls auftreten kann. Ein try except-Block fängt die Ausnahme möglicherweise ab, behebt sie jedoch nicht, es sei denn, er wurde ausdrücklich dazu geschrieben. Es scheint einfacher zu sein, die Korrekturzeile (n) unmittelbar nach der a- Berechnungszeile zu codieren . Eine gründlich bereinigte Eingabe sollte dann keinen Versuch erfordern, außer hier überhaupt zu blockieren.
Zusammenfassung: Wenn Sie Haversine verwenden, das explizit codiert ist, anstatt ein Paket oder eine Bibliothek zu verwenden, ist es unabhängig von der Sprache Ihrer Wahl eine gute Idee, es zu testen und zu normalisieren , einen zurück in den nötigen Bereich von 0,0 <= a <= 1,0 um um die nächste Zeile mit ihren c- Berechnungenzu schützen. Aber die Mehrheit der Haversine-Code-Schnipsel zeigt es nicht an und erwähnt das Risiko nicht.
Erfahrung: Während gründlicher Tests rund um den Globus habe ich in Schritten von 0,001 Grad eine Festplatte mit Lat-Lon-Kombinationen gefüllt, die eine Ausnahme verursacht haben, eine zuverlässig konsistente, wiederholbare Ausnahme, während eines Monats, in dem auch die Zuverlässigkeit der CPU-Kühlung überprüft wurde Fan und meine Geduld. Ja, ich habe seitdem die meisten dieser Protokolle gelöscht, da ihr Zweck hauptsächlich darin bestand, den Sinn zu beweisen (wenn das Wortspiel erlaubt ist). Aber ich habe einige kürzere Protokolle von 'Problem-Lat-Lon-Werten', die zu Testzwecken aufbewahrt werden.
Genauigkeit: Will Verliert a und das gesamte Haversine-Ergebnis an Genauigkeit, wenn es wieder ein wenig in die Domäne normalisiert wird? Nicht viel, vielleicht nicht mehr als die bereits eingeführten fp64-Annäherungen und -Rundungen, die zu dieser leichten Abweichung aus dem Bereich führten. Wenn Sie festgestellt haben, dass Haversine bereits über hundert Mal akzeptabel ist - einfacher, schneller, einfacher anzupassen, zu beheben und zu warten -, ist Haversine möglicherweise eine gute Lösung für Ihr Projekt.
Ich habe Haversine auf einer über Kopf projizierten Himmelskugel verwendet, um Winkelabstände zwischen Objekten am Himmel zu messen, wie von einer Position auf der Erde aus gesehen, Azimut und Alt auf Lat-Lon-Äquivalent-Koordinaten des Himmels abgebildet Die projizierte theoretische Himmelssphäre ist eine perfekte Kugel, wenn es darum geht, Blickwinkel zwischen zwei Objekten von einer Position auf der Erdoberfläche aus zu messen. Es passt perfekt zu meinen Bedürfnissen. Also, Haversine ist immer noch sehr nützlich und in bestimmten Anwendungen sehr genau (genau für meine Zwecke) ... aber wenn Sie es verwenden, ob auf der Erde für GIS oder Navigation oder bei Beobachtungen und Messungen von Himmelsobjekten, schützen Sie es es im Fall von Antipodenpunkten oder sehr nahen Antipodenpunkten durch Testen von aund stupsen Sie es zurück in seine benötigte Domäne, wenn nötig.
Das ungeschützte Haversine ist im gesamten Internet zu finden, und ich habe nur einen alten Usenet-Beitrag gesehen, der, wie ich glaube, vor jemandem von JPL geschützt war und der möglicherweise vor 1985 laut Gleitkomma-Spezifikation IEEE 754 erstellt wurde. Zwei andere Seiten erwähnten mögliche Probleme in der Nähe von Antipodenpunkten, beschrieben diese jedoch nicht oder wie man sie mildern könnte. Aus diesem Grund gibt es Bedenken für Neulinge (wie mich), die die bewährten Methoden möglicherweise nicht immer gut genug verstehen, um einige Codes, die sie kopiert und in ein vertrauenswürdiges Projekt eingefügt haben, weiter zu untersuchen und zu testen. Der faszinierende Beitrag von cffk war insofern erfrischend, als er öffentlich mit diesen Arten von Problemen bekannt war, die nicht oft erwähnt, selten öffentlich zum Schutz in Snippets codiert und selten auf diese Weise diskutiert wurden, verglichen mit der Menge ungeschützter und nicht diskutierter Versionen, die veröffentlicht wurden.
Ab 20190923 wird auf der Wiki-Seite für Haversine-Formeln in der Tat das Problem erwähnt, das aufgrund von Gleitkommaproblemen in Computergeräten an Antipodenpunkten auftreten kann ... ermutigend ...
https://en.wikipedia.org/wiki/Haversine_formula
(Da diese Wiki-Seite zu diesem Zeitpunkt keinen HTML-Anker für den Abschnitt hat, auf den ich direkt verweisen würde, führen Sie nach dem Laden der Seite eine Suche auf dieser Browserseite nach "Wenn Sie diese Formeln verwenden" durch, und Sie werden es tun siehe das Problem der Haversine mit den erwähnten Antipodenpunkten, genauer gesagt.)
Und diese andere Seite hat auch eine sehr kurze Erwähnung davon:
https://www.movable-type.de/scripts/latlong.html
Wenn man auf dieser Seite nach "Schutz vor Rundungsfehlern" sucht, gibt es diese ...
Wenn atan2 nicht verfügbar ist, kann c aus 2 Asin (min (1, √a)) berechnet werden (einschließlich des Schutzes vor Rundungsfehlern).
Jetzt gibt es einen seltenen Fall, in dem Rundungsfehler erwähnt und der Schutz für die Version asin () angezeigt wird, jedoch für die Version atan2 () nicht erwähnt oder angezeigt wird. Es wird aber zumindest auf die Gefahr von Rundungsfehlern hingewiesen.
imho, jede 24/7/365 Anwendung mit Haversine, benötigt diesen Schutz in der Nähe der Antipodenpunkte als wichtiges und einfaches Detail.
Ich weiß nicht, welche haversine-Pakete diesen Schutz enthalten oder nicht, aber wenn Sie mit all dem noch nicht vertraut sind und die im Fachjargon veröffentlichten "Snippet" -Versionen verwenden möchten, wissen Sie jetzt, dass sie geschützt werden müssen, und Dieser Schutz ist sehr einfach zu implementieren, d. h., wenn Sie nicht vincenty und keinen verpackten Haversine ohne einfachen Zugriff zum Ändern des Code des Pakets verwenden.
IOW, egal ob mit vincenty oder haversine oder sloc, man sollte sich über Probleme mit dem Code im Klaren sein, Dinge, auf die man achten und die man mindern muss, und wie man mit vincenty gegen haversine gegen sloc umgeht, wird sich unterscheiden, wenn man sich seiner bewusst wird Lauernde Probleme / Edgecases, die allgemein bekannt sein können oder nicht.