Sia che utilizzi vincenty o haversine o la legge sferica dei coseni, c'è saggezza nel prendere coscienza di eventuali problemi potenziali con il codice che stai pianificando di usare, cose a cui fare attenzione e mitigare, e come si affrontano le questioni vincenty vs haversine vs sloc differirà man mano che si diventa consapevoli dei problemi in agguato di ciascuno, che possono o meno essere conosciuti popolarmente. Il programmatore esperto lo sa. I principianti non possono. Spero di risparmiare alcuni di loro frustrazione quando uno snippet di un forum fa qualcosa di inaspettato, in alcuni casi. Se si utilizzerà seriamente una versione di uno di questi, vincenty, haversine, sloc, allora SE, SO, Reddit, Quora, ecc., Potrebbero aver fornito un aiuto limitato in alcuni codici iniziali di una soluzione, ma ciò non significa che la loro soluzione o la "risposta" accettata è priva di problemi. Se un progetto è abbastanza importante, merita un'adeguata quantità ragionevole di ricerca. Leggi il manuale, leggi i documenti e, se esiste una revisione del codice di quel codice, leggilo. Copiare e incollare uno snippet o un gist che è stato votato centinaia o più volte non significa che la sua sicurezza sia completa e garantita.
La risposta intrigante pubblicata da cffk solleva il punto di essere a conoscenza di agguati di edgecase, in soluzioni confezionate, che possono produrre eccezioni o altre difficoltà . Le affermazioni specifiche fatte in quel post sono al di là del mio budget di tempo da perseguire al momento, ma tolgo da esso che ci sono davvero problemi in agguato in alcuni pacchetti, inclusa almeno un'implementazione vincenty, riguardo alla quale almeno una persona ha proposto di migliorare in un modo o nell'altro, al fine di ridurre al minimo o eliminare il rischio di incontrare tali difficoltà. Non approfondirò ulteriormente l'argomento relativo a vincenty (essendo troppo troppo ignorante), ma passerò invece a haversine, almeno in parte sull'argomento con l'OP.
La formula haversine pubblicata pubblicamente, sia in pitone che in un'altra lingua, perché molto probabilmente utilizzerà le specifiche IEEE 754 in virgola mobile sulla maggior parte di tutti i sistemi Intel e Intel, e processori ARM, powerPC, ecc. essere suscettibile anche a rari ma reali e ripetibili errori di eccezione molto vicini o ad una distanza dell'arco di 180 gradi, punti antipodali, a causa di approssimazioni in virgola mobile e arrotondamenti. Alcuni principianti potrebbero non essere ancora stati morsi da questa situazione. Poiché questa specifica fp si avvicina e arrotonda, ciò non significa che qualsiasi codice che chiama fp64 potrebbe causare errori di eccezione, no. Ma un po 'di codice, alcune formule potrebbero non avere edgecase così evidenti in cui le approssimazioni e gli arrotondamenti di IEEE 754 fp64 potrebbero far deviare leggermente un valore dal dominio di un metodo matematico che dovrebbe valutare in modo impeccabile tale valore. Un esempio ... sqrt (). Se un valore negativo viene inserito in un sqrt (), come sqrt (-0.00000000000000000122739), si verificherà un errore di eccezione. Nella formula haversine, il modo in cui progredisce verso una soluzione, ci sono due metodi sqrt () nell'atan2 (). Ila che viene calcolato e quindi utilizzato in sqrt (), può, nei punti antipodali del globo, leggermente vagare sotto 0,0 o sopra 1,0, molto leggermente a causa delle approssimazioni e degli arrotondamenti di fp64, raramente, ma ripetibilmente. La ripetibilità affidabile e coerente, in questo contesto, rende questo rischio eccezionale, una custodia per proteggere, mitigare, piuttosto che un colpo di fortuna casuale isolato. Ecco un esempio di un breve frammento di python3 di haversine, senza la protezione necessaria:
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
Molto vicino o nei punti antipodali, un calcolato nella prima riga della formula può vagare negativamente, raramente, ma ripetibilmente con le stesse coordinate lat lon. Per proteggere / correggere quei casi rari, si può semplicemente aggiungere, dopo l' una di calcolo, come si vede qui sotto:
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
Ovviamente non ho mostrato l'intera funzione qui, ma un breve frammento come spesso pubblicato. Ma questo mostra la protezione per sqrt (), testando la a e normalizzandola se necessario, risparmiando anche la necessità di provare tutto tranne. La nota = '' up top serve per impedire allo stage bytecode di protestare sul fatto che la nota viene utilizzata prima che gli venga assegnato un valore, se viene restituito con il risultato della funzione.
Con questa semplice modifica, l'aggiunta dei due a test, le funzioni sqrt () saranno felici e il codice ora ha una nota aggiuntiva che può essere restituita al codice chiamante, per avvisare che un risultato è stato leggermente normalizzato e perché. Ad alcuni potrebbe interessare, altri potrebbero non farlo, ma è lì, a prevenire un errore di eccezione, che altrimenti si può verificare. Un tentativo tranne il blocco può catturare l'eccezione, ma non risolverlo, a meno che non sia scritto esplicitamente per farlo. Sembra più facile codice linea di correzione (s) immediatamente dopo l' una riga di calcolo. Un input accuratamente pulito non dovrebbe quindi richiedere un tentativo, tranne un blocco qui.
Riepilogo, se si utilizza haversine, codificato esplicitamente anziché utilizzare un pacchetto o una libreria, indipendentemente dalla lingua prescelta, sarebbe una buona idea testare e normalizzare un ritorno nell'intervallo necessario di 0,0 <= a <= 1.0 in ordine per proteggere la riga successiva con i suoi calcoli c . Ma la maggior parte degli snippet di codice haversine non lo mostra e non menziona il rischio.
Esperienza: durante test approfonditi in tutto il mondo, con incrementi di 0,001 gradi, ho riempito un disco rigido con combinazioni lat lon che hanno causato un'eccezione, un'eccezione affidabile ripetibile e coerente, durante un mese di test collaterale anche l'affidabilità del raffreddamento della CPU fan e la mia pazienza. Sì, da allora ho cancellato la maggior parte di quei registri, poiché il loro scopo era principalmente quello di dimostrare il punto (se il gioco di parole è permesso). Ma ho alcuni registri più brevi di "valori lat lon problem", tenuti a scopo di test.
Precisione: a e l'intero risultato di haversine perderanno un po 'di precisione normalizzandolo di nuovo un po' nel dominio? Non molto, forse non più che le approssimazioni e gli arrotondamenti di fp64 stavano già introducendo, ciò ha causato quella leggera deviazione dal dominio. Se hai già trovato che haversine è accettabile rispetto a vincenty - più semplice, più veloce, più facile da personalizzare, risolvere i problemi e mantenere, allora haversine potrebbe essere una buona soluzione per il tuo progetto.
Ho usato haversine su uno skysphere proiettato in alto per misurare le distanze angolari tra gli oggetti nel cielo, visto da una posizione sulla terra, mappando azimut e alt a skysphere lat lon coordinate equivalenti, nessun elipsoide da considerare, dal momento che il la skysphere teorica proiettata è una sfera perfetta, quando si tratta di misurare la distanza angolare osservando gli angoli tra due oggetti da una posizione sulla superficie terrestre. Si adatta perfettamente alle mie esigenze. Quindi, haversine è ancora molto utile, e molto preciso, in alcune applicazioni (ben entro i miei scopi) ... ma se lo usi, sulla terra per GIS o navigazione, o in osservazioni e misurazioni di oggetti del cielo, proteggi nel caso di punti antipodali o punti antipodali molto vicini, mediante test ae spingendolo di nuovo nel suo dominio necessario quando necessario.
L'haversine non protetto è su Internet, e ho visto solo un vecchio post usenet che mostrava una certa protezione, penso da qualcuno della JPL, e che potrebbe essere stato prima del 1985, prima della IEEE 754 in virgola mobile. Altre due pagine menzionavano possibili problemi in prossimità di punti antipodali, ma non descrivevano tali problemi o come si potesse mitigarli. Quindi c'è preoccupazione per i neofiti (come me) che potrebbero non sempre comprendere le buone pratiche abbastanza bene per approfondire la ricerca e testare le edgecase, di alcuni codici che hanno copiato e incollato in un progetto di fiducia. L'intrigante post di cffk è stato rinfrescante in quanto era pubblico con questi tipi di problemi, che non sono spesso menzionati, raramente codificati pubblicamente per la protezione in frammenti, e raramente discussi in questo modo, rispetto alla quantità di versioni non protette e non discusse che vengono pubblicate.
A partire da 20190923, la pagina wiki per la formula di haversine menziona effettivamente il problema possibile nei punti antipodali, a causa di problemi in virgola mobile nei dispositivi di elaborazione ... incoraggiante ...
https://en.wikipedia.org/wiki/Haversine_formula
(perché quella pagina wiki non ha, in questo momento, un'ancora html per la sezione a cui vorrei collegarmi direttamente, quindi, dopo che la pagina è stata caricata, fai una ricerca su quella pagina del browser per "Quando usi queste formule" e vedere il problema di haversine con i punti antipodali menzionati, più ufficialmente.)
E anche questo altro sito ne parla brevemente:
https://www.movable-type.co.uk/scripts/latlong.html
Se uno trova su quella pagina per "includere la protezione contro gli errori di arrotondamento", c'è questo ...
Se atan2 non è disponibile, c potrebbe essere calcolato da 2 ⋅ asin (min (1, √a)) (inclusa la protezione contro gli errori di arrotondamento).
Ora c'è un raro caso in cui sono menzionati errori di arrotondamento e protezione mostrata per la versione asin (), ma non menzionata o mostrata per la versione atan2 (). Ma almeno viene menzionato il rischio di errori di arrotondamento.
imho, qualsiasi applicazione 24/7/365 che utilizza haversine, ha bisogno di questa protezione vicino ai punti antipodali come un dettaglio importante e semplice.
Non so quali pacchetti di haversine includano o non includano questa protezione, ma se sei nuovo in tutto questo e utilizzerai le versioni 'snippet' pubblicamente pubblicate, ora sai che ha bisogno di protezione e tale protezione è molto semplice da implementare, vale a dire, se non si utilizza vincenty e non si utilizza un pacchetto confezionato senza un facile accesso per modificare il codice del pacchetto.
IOW, sia che si utilizzi vincenty o haversine o sloc, si dovrebbe essere consapevoli di eventuali problemi con il codice, le cose a cui prestare attenzione e mitigare e come si affrontano i problemi vincenty vs haversine vs sloc differiranno quando si diventa consapevoli di ognuno in agguato problemi / edgecase, che possono o meno essere conosciuti popolarmente.