Modo numericamente stabile di calcolare gli angoli tra i vettori


14

Quando si applica la formula classica per l'angolo tra due vettori:

α=arccosv1v2v1v2

si rileva che, per angoli molto piccoli / acuti, si verifica una perdita di precisione e il risultato non è accurato. Come spiegato in questa risposta Stack Overflow , una soluzione è utilizzare invece arctangent:

α=arctan2(v1×v2,v1v2)

E questo in effetti dà risultati migliori. Tuttavia, mi chiedo se questo darebbe cattivi risultati per angoli molto vicini a π/2 . È il caso? In tal caso, esiste una formula per calcolare accuratamente gli angoli senza verificare la tolleranza all'interno di un iframo?


1
Questo dipenderà dall'implementazione della funzione tangente inversa a due parametri. Le versioni lente e stabili cambiano condizionatamente tra lavorare con x / y e y / x per mantenere la precisione, mentre quelle veloci attaccano semplicemente le cose nel quadrante giusto e quindi non sono più precise della versione con un parametro.
origimbo,

Dovresti definire "perdita di precisione": supponi che la risposta giusta sia e ottieni invece . Hai bisogno di o è sufficiente? αα+ΔΔαΔπ
Stefano M,

In questo caso, la risposta giusta era e ho ottenuto , entrambi . α 10 81αα1081
astrojuanlu,

Risposte:


18

( Ho già provato questo approccio e ricordo che ha funzionato correttamente, ma non l'ho testato specificamente per questa domanda. )

Per quanto ne so, entrambi e possono soffrire di cancellazione catastrofica se sono quasi paralleli / perpendicolari: atan2 non può darti una buona precisione se uno dei due input è disattivato.v 1v 2v1×v2v1v2

Inizia riformulando il problema come trovare l'angolo di un triangolo con lunghezze laterali,e(questi sono tutti accuratamente calcolati in aritmetica in virgola mobile). Esiste una variante ben noto di formula di Heron causa Kahan ( miscalculating Area e angoli di un aghiforme Triangle ), che permette di calcolare l'area e l'angolo (tra e ) di un triangolo specificato dai relativi lunghezze laterali, e farlo numericamente stabilmente. Poiché anche la riduzione a questo sottoproblema è accurata, questo approccio dovrebbe funzionare con input arbitrari.b = | v 2 | c = | v 1 - v 2 | a ba=|v1|b=|v2|c=|v1v2|ab

Citando da quel documento (vedi p.3), assumendo , Tutte le parentesi qui sono posizionate con cura e contano; se ti ritrovi a prendere la radice quadrata di un numero negativo, le lunghezze dei lati di input non sono le lunghezze dei lati di un triangolo.ab

μ={c(ab),if bc0,b(ac),if c>b0,invalid triangle,otherwise
angle=2arctan(((ab)+c)μ(a+(b+c))((ac)+b))

C'è una spiegazione di come funziona, inclusi esempi di valori per i quali altre formule falliscono, nel documento di Kahan. La tua prima formula per è a pagina 4.C αC

Il motivo principale per cui suggerisco che la formula dell'airone di Kahan sia perché rende una primitiva molto bella: molte domande di geometria planare potenzialmente complicate possono essere ridotte alla ricerca dell'area / angolo di un triangolo arbitrario, quindi se puoi ridurre il tuo problema a quello, c'è una buona formula stabile per questo, e non c'è bisogno di inventare qualcosa da soli.

Modifica Dopo il commento di Stefano, ho fatto una trama di errore relativo per , ( codice ). Le due righe sono gli errori relativi di e , che si lungo l'asse orizzontale. Sembra che funzioni. v 2 = ( cos θ , sin θ ) θ = ϵ θ = π / 2 - ϵ ϵv1=(1,0)v2=(cosθ,sinθ)θ=ϵθ=π/2ϵϵinserisci qui la descrizione dell'immagine


Grazie per il link e la risposta! Sfortunatamente la seconda formula che ho scritto non appare nell'articolo. D'altra parte, questo metodo può diventare un po 'complesso, poiché richiede la proiezione in 2D.
astrojuanlu,

2
@astrojuanlu Non c'è proiezione a 2d qui: qualunque siano i due vettori 3d, essi definiscono un singolo triangolo (planare) tra di loro - devi solo conoscerne le lunghezze laterali.
Kirill,

Hai ragione, il mio commento non ha senso. Stavo pensando in coordinate anziché in lunghezze. Grazie ancora!
astrojuanlu,

2
@astrojuanlu Un'altra cosa che voglio notare: sembra che ci sia una prova formale che la formula dell'area sia accurata in Come calcolare l'area di un triangolo: una rivisitazione formale , Sylvie Boldo , usando Flocq.
Kirill,

Ottima risposta, ma contesto che puoi sempre calcolare con precisione in aritmetica in virgola mobile. In effetti se si verificano cancellazioni catastrofiche nel calcolo dei componenti di . cc<ϵmin(a,b)(v1v2)
Stefano M,

7

La risposta efficace a questa domanda è, non troppo sorprendentemente, in un'altra nota di Velvel Kahan :

α=2arctan(v1v1+v2v2,v1v1v2v2)

dove uso come angolo creato da con l'asse orizzontale. (Potrebbe essere necessario invertire l'ordine degli argomenti in alcune lingue.)arctan(x,y)(x,y)

(Ho fatto una dimostrazione di Mathematica della formula di Kahan qui .)


Intendi ? arctan2
astrojuanlu,

1
Sono abituato a rappresentare solo l'arcotangente a due argomenti come , sì. In una lingua come FORTRAN, l'equivalente sarebbe . arctan(x,y)ATAN2(Y, X)
JM,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.