Niezależnie od tego, czy używasz vincenty, haverine, czy sferycznego prawa cosinusów, mądrość polega na uświadomieniu sobie wszelkich potencjalnych problemów z kodem, którego planujesz użyć, rzeczy, na które należy uważać i które można złagodzić, oraz tego, jak radzić sobie z problemami vincenty vs. haversine vs. sloc będą się różnić, gdy uświadomimy sobie czyjeś czyhające problemy / obramowania, które mogą, ale nie muszą być powszechnie znane. Doświadczony programista wie o tym. Początkujący mogą nie. Mam nadzieję zaoszczędzić niektórym z nich frustracji, gdy fragment kodu z forum robi coś nieoczekiwanego, w niektórych przypadkach. Jeśli ktoś poważnie zamierza zastosować jakąś wersję któregokolwiek z nich, Vincenty, haverine, sloc, to SE, SO, Reddit, Quora itp., Może zapewnić ograniczoną pomoc w początkowym kodowaniu rozwiązania, ale to nie znaczy, że ich rozwiązanie lub zaakceptowana „odpowiedź” jest wolna od problemów. Jeśli projekt jest wystarczająco ważny, zasługuje na odpowiednią rozsądną ilość badań. Przeczytaj instrukcję, przeczytaj dokumentację, a jeśli istnieje przegląd kodu tego kodu, przeczytaj go. Skopiowanie i wklejenie fragmentu lub treści, która została oceniona sto lub więcej razy, nie oznacza, że jego bezpieczeństwo jest wszechstronne i pewne.
Intrygująca odpowiedź wysłana przez cffk podnosi świadomość, że czają się przypadkowe przypadki w opakowanych rozwiązaniach, które mogą powodować wyjątki lub inne trudności . Konkretne twierdzenia zawarte w tym poście przekraczają obecnie mój budżet czasowy, ale zabieram z tego, że w niektórych pakietach, w tym co najmniej jednej implementacji vincenty, rzeczywiście istnieją problemy, w których co najmniej jedna osoba zaproponowała poprawę w taki czy inny sposób, aby zminimalizować lub wyeliminować ryzyko napotkania tych trudności. Nie będę dodawał więcej do tego tematu dotyczącego Vincenty (będąc zbyt zbyt nieświadomym), ale zamiast tego przejdę do haversine, przynajmniej częściowo na temat z PO.
Popularnie opublikowana formuła haverine, czy to w Pythonie, czy w innym języku, ponieważ najprawdopodobniej będzie korzystała ze specyfikacji zmiennoprzecinkowej IEEE 754 w większości wszystkich systemów Intel i podobnych do Intel, a także procesorów ARM, powerPC itp. być również podatnym na rzadkie, ale rzeczywiste i powtarzalne błędy wyjątków bardzo bliskie lub w odległości 180 stopni łuku, punkty antypodalne, z powodu przybliżeń zmiennoprzecinkowych i zaokrąglania. Niektórzy nowicjusze mogą jeszcze nie zostać ukąszeni przez tę sytuację. Ponieważ ta specyfikacja fp jest przybliżona i zaokrągla, nie oznacza to, że każdy kod wywołujący fp64 może powodować błędy wyjątków, nie. Ale trochę kodu niektóre formuły mogą nie mieć tak oczywistych przypadków, w których aproksymacje i zaokrąglenia IEEE 754 fp64 mogą powodować, że wartość nieznacznie wykracza poza dziedzinę metody matematycznej, która, jak się oczekuje, bezbłędnie oceni taką wartość. Przykład ... sqrt (). Jeśli wartość ujemna znajdzie się w sqrt (), takiej jak sqrt (-0.00000000000000000122739), wystąpi błąd wyjątku. We wzorze haverine, w którym postępuje on w kierunku rozwiązania, istnieją dwie metody sqrt () w atan2 (). Thea, który jest obliczany, a następnie stosowany w sqrt (), może w punktach antypodalnych na kuli ziemskiej nieco zbłądzić poniżej 0,0 lub powyżej 1,0, bardzo nieznacznie z powodu przybliżeń fp64 i zaokrąglania, rzadko, ale powtarzalnie. Konsekwentna niezawodna powtarzalność w tym kontekście sprawia, że jest to wyjątkowe ryzyko, przypadek do ochrony, łagodzenia, a nie izolowany losowy przypadek. Oto przykład krótkiego fragmentu haversine w Pythonie bez niezbędnej ochrony:
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
Bardzo blisko lub na antypodyczne punktów oblicza się w pierwszym wierszu wzoru może zboczyć ujemny, rzadko, ale z tymi samymi repeatably łac współrzędnych Lon. Aby zabezpieczyć / skorygowania tych rzadkich przypadków, można po prostu dodać, po w obliczeniach, jak widać poniżej:
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
Oczywiście nie pokazałem tutaj całej funkcji, ale krótki fragment, który jest tak często publikowany. Ale ten pokazuje ochronę sqrt (), testując a i normalizując go, jeśli to konieczne, oszczędzając również potrzeby wypróbowania całości. Uwaga = '' góra do góry ma zapobiegać protestowaniu przez kod bajtowy, że nuta jest używana przed przypisaniem wartości, jeśli zostanie zwrócona z wynikiem funkcji.
Po tej prostej zmianie, dodając dwa testy a , funkcje sqrt () będą zadowolone, a kod ma teraz dodatkową notatkę, którą można zwrócić do kodu wywołującego, aby ostrzec, że wynik został nieco znormalizowany i dlaczego. Niektórzy mogą się tym przejmować, inni nie, ale to tam, zapobiegając błędowi wyjątku, który w przeciwnym razie może wystąpić. Blok try try może przechwycić wyjątek, ale go nie naprawić, chyba że jest to wyraźnie napisane. Wydaje się łatwiej kodzie Correction (s) natychmiast po linią obliczeniowej. Dokładnie wyszorowane wejście nie powinno wtedy wymagać próby, z wyjątkiem bloku tutaj.
Podsumowanie, jeśli używasz haversine, kodowanego jawnie zamiast pakietu lub biblioteki, bez względu na wybrany język, dobrym pomysłem byłoby przetestowanie i znormalizowanie z powrotem do wymaganego zakresu 0,0 <= a <= 1,0 w kolejności aby chronić następny wiersz z jego obliczeniami c . Ale większość fragmentów kodu haverine nie pokazuje tego i nie wspomina o ryzyku.
Doświadczenie: podczas dokładnych testów na całym świecie, w przyrostach co 0,001 stopnia, napełniłem dysk twardy kombinacjami lat lon, które spowodowały wyjątek, niezawodny spójny powtarzalny wyjątek, w ciągu miesiąca równolegle testującego niezawodność chłodzenia procesora fanem i moją cierpliwością. Tak, od tego czasu usunąłem większość tych dzienników, ponieważ ich celem było głównie udowodnienie sensu (jeśli kalambur jest dozwolony). Mam jednak krótsze dzienniki „problematycznych wartości lontu”, przechowywane do celów testowych.
Dokładność: czy a i cały wynik haverine straci pewną dokładność poprzez normalizację tego małego kawałka z powrotem do dziedziny? Niewiele, może nie więcej niż przybliżenia fp64 i zaokrąglenia już były wprowadzane, co spowodowało to nieznaczne przesunięcie poza domenę. Jeśli uznasz, że haversine jest już akceptowalny w stosunku do vincenty - prostsze, szybsze, łatwiejsze do dostosowania, rozwiązywania problemów i konserwacji, haversine może być dobrym rozwiązaniem dla twojego projektu.
Użyłem haversine na rzutowanej sferze nieba do pomiaru odległości kątowych między obiektami na niebie, widzianej z pozycji na ziemi, mapowania azymutu i alt na sferę lat współrzędnych podobnych do współrzędnych, żadnych elipsoid w ogóle do rozważenia, ponieważ rzutowana teoretyczna kula nieba jest idealną kulą, jeśli chodzi o pomiar odległości kątowej kątów patrzenia między dwoma obiektami z pozycji na powierzchni ziemi. Idealnie odpowiada moim potrzebom. Tak więc, haversine jest nadal bardzo przydatny i bardzo dokładny w niektórych aplikacjach (dobrze w moich celach) ... ale jeśli go użyjesz, czy to na ziemi do GIS lub nawigacji, lub w obserwacjach i pomiarach obiektów nieba, chroń to w przypadku antypodyczne punktów lub bardzo blisko antypodyczne punktów, testując Ai w razie potrzeby umieszczając go z powrotem w niezbędnej domenie.
Niechroniony haverine jest dostępny w całym Internecie i widziałem tylko jeden stary post usenet, który pokazał pewną ochronę, myślę, że od kogoś z JPL, i może to być wcześniejsza wersja zmiennoprzecinkowa sprzed 1985 r., IEEE 754. Dwie inne strony wspomniały o możliwych problemach w pobliżu punktów antypodalnych, ale nie opisały tych problemów ani sposobów ich złagodzenia. Pojawiają się więc obawy początkujących (takich jak ja), którzy nie zawsze rozumieją dobre praktyki na tyle dobrze, aby dalej badać i testować edgecases niektórych kodów, które skopiowali i wkleili w zaufany projekt. Intrygujący post cffk był odświeżający, ponieważ był publiczny z tego rodzaju problemami, które nie są często wspominane, rzadko publicznie kodowane dla ochrony we fragmentach i rzadko omawiane w ten sposób, w porównaniu do liczby opublikowanych niechronionych i nieopisanych wersji.
W wersji 20190923 strona wiki dotycząca formuły haverine faktycznie wspomina o problemie możliwym w punktach antypodalnych z powodu problemów z zmiennoprzecinkowymi urządzeniami komputerowymi ... zachęcając ...
https://en.wikipedia.org/wiki/Haversine_formula
(ponieważ ta strona wiki nie ma w tej chwili kotwicy HTML dla sekcji, do której prowadziłbym bezpośredni link, dlatego po załadowaniu strony wyszukaj na tej stronie przeglądarki hasło „Podczas korzystania z tych formuł”, a zobacz problem haversine ze wspomnianymi punktami antypodalnymi, bardziej oficjalnie).
I ta druga strona również bardzo krótko o tym wspomina:
https://www.movable-type.co.uk/scripts/latlong.html
Jeśli ktoś znajdzie na tej stronie wyrażenie „w tym ochrona przed błędami zaokrąglania”, istnieje ...
Jeśli atan2 nie jest dostępny, c można obliczyć z 2 ⋅ asin (min (1, √a)) (w tym ochrona przed błędami zaokrąglania).
Teraz jest rzadki przypadek, w którym wspomniane są błędy zaokrąglania, a ochrona jest pokazywana dla wersji asin (), ale nie jest wymieniona ani pokazana dla wersji atan2 (). Ale wspomniane jest przynajmniej ryzyko błędów zaokrąglania.
Imho, każda aplikacja 24/7/365 korzystająca z haverine, potrzebuje tej ochrony w pobliżu punktów antypodalnych jako ważny i prosty szczegół.
Nie wiem, które pakiety haversine zawierają lub nie obejmują tej ochrony, ale jeśli jesteś nowy w tym wszystkim i zamierzasz używać popularnie opublikowanych wersji „snippet”, teraz wiesz, że potrzebuje ochrony, i ta ochrona jest bardzo łatwa do wdrożenia, to znaczy, jeśli nie używasz vincenty i nie używasz spakowanego haverine bez łatwego dostępu do modyfikacji kodu pakietu.
IOW, niezależnie od tego, czy używasz vincenty, haversine czy sloc, należy zdawać sobie sprawę z wszelkich problemów z kodem, rzeczy, na które należy uważać i je łagodzić, oraz to, jak radzimy sobie z problemami vincenty vs. haversine vs. czające się problemy / edgecases, które mogą, ale nie muszą być powszechnie znane.