Saat menerapkan rumus klasik untuk sudut antara dua vektor:
orang menemukan bahwa, untuk sudut yang sangat kecil / akut, ada kehilangan presisi dan hasilnya tidak akurat. Seperti yang dijelaskan dalam jawaban Stack Overflow ini , salah satu solusinya adalah menggunakan arctangent sebagai gantinya:
Dan ini memang memberikan hasil yang lebih baik. Namun, saya bertanya-tanya apakah ini akan memberikan hasil yang buruk untuk sudut yang sangat dekat dengan . Apakah ini masalahnya? Jika demikian, apakah ada rumus untuk menghitung sudut secara akurat tanpa memeriksa toleransi di dalam if
cabang?
algorithms
precision
numerical-limitations
astrojuanlu
sumber
sumber
Jawaban:
( Saya telah menguji pendekatan ini sebelumnya, dan saya ingat itu berhasil dengan benar, tetapi saya belum mengujinya secara khusus untuk pertanyaan ini. )
Sejauh yang saya tahu, keduanya dan dapat menderita pembatalan besar jika hampir paralel / tegak lurus — atan2 tidak dapat memberikan akurasi yang baik jika salah satu input dimatikan.∥v1×v2∥ v1⋅v2
Mulailah dengan merumuskan kembali masalah sebagai menemukan sudut segitiga dengan panjang sisi,dan(Ini semua dihitung secara akurat dalam aritmatika floating point). Ada varian rumus Heron yang terkenal karena Kahan ( Area salah hitung dan Sudut Segitiga yang Seperti Jarum ), yang memungkinkan Anda menghitung luas dan sudut (antara dan ) dari sebuah segitiga yang ditentukan oleh panjang sisinya, dan melakukannya secara stabil secara numerik. Karena pengurangan subproblem ini juga akurat, pendekatan ini harus bekerja untuk input yang sewenang-wenang.a=|v1| b=|v2| c=|v1−v2| a b
Mengutip dari makalah itu (lihat hal.3), dengan asumsi , Semua kurung di sini ditempatkan dengan hati-hati, dan mereka peduli; jika Anda menemukan diri Anda mengambil akar kuadrat dari angka negatif, panjang sisi input bukan panjang sisi segitiga.a≥b
Ada penjelasan tentang bagaimana ini bekerja, termasuk contoh nilai yang gagal rumus lainnya, dalam makalah Kahan. Formula pertama Anda untuk adalah di halaman 4.α C′′
Alasan utama saya menyarankan rumus Kahan's Heron adalah karena itu membuat primitif yang sangat bagus — banyak pertanyaan geometri planar yang berpotensi rumit dapat direduksi menjadi menemukan area / sudut segitiga sembarang, jadi jika Anda dapat mengurangi masalah Anda menjadi itu, ada formula stabil yang bagus untuk itu, dan tidak perlu untuk membuat sesuatu sendiri.
Sunting Mengikuti komentar Stefano, saya membuat plot kesalahan relatif untuk , ( kode ). Dua baris tersebut adalah kesalahan relatif untuk dan , sepanjang sumbu horizontal. Tampaknya itu berfungsi.v1=(1,0) v2=(cosθ,sinθ) θ=ϵ θ=π/2−ϵ ϵ
sumber
Jawaban efisien untuk pertanyaan ini, tidak terlalu mengejutkan, dalam catatan lain oleh Velvel Kahan :
di mana saya menggunakan sebagai sudut yang dibuat oleh dengan sumbu horizontal. (Anda mungkin harus membalik urutan argumen dalam beberapa bahasa.)arctan(x,y) (x,y)
(Saya memberikan demonstrasi Mathematica dari formula Kahan di sini .)
sumber
ATAN2(Y, X)