( 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 1 ⋅ v 2∥v1×v2∥v1⋅v2
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=|v1−v2|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.a≥b
μ=⎧⎩⎨c−(a−b),b−(a−c),invalid triangle,if b≥c≥0,if c>b≥0,otherwise
angle=2arctan(((a−b)+c)μ(a+(b+c))((a−c)+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−ϵϵ