Saya ingin membandingkan sudut dan mendapatkan gagasan tentang jarak di antara mereka. Untuk aplikasi ini, saya bekerja dalam derajat, tetapi itu juga berfungsi untuk radian dan lulusan. Masalah dengan sudut adalah bahwa mereka bergantung pada aritmatika modular, yaitu 0-360 derajat.
Katakan satu sudut di 15 derajat dan satu di 45. Perbedaannya adalah 30 derajat, dan sudut 45 derajat lebih besar dari 15 derajat.
Tapi, ini rusak ketika Anda memiliki, katakanlah, 345 derajat dan 30 derajat. Meskipun mereka membandingkan dengan benar, perbedaan di antara mereka adalah 315 derajat, bukan 45 derajat yang benar.
Bagaimana saya bisa memecahkan masalah ini? Saya bisa menulis kode algoritmik:
if(angle1 > angle2) delta_theta = 360 - angle2 - angle1;
else delta_theta = angle2 - angle1;
Tapi saya lebih suka solusi yang menghindari membandingkan / cabang, dan bergantung sepenuhnya pada aritmatika.
sumber
Jawaban:
Inilah versi saya yang disederhanakan, tanpa cabang, bebas-perbandingan, tanpa min / maks:
Menghapus modulo, karena inputnya cukup terbatas (terima kasih kepada Martin karena menunjukkannya).
Dua abs, tiga kurangi.
sumber
Apa yang membuat Anda berpikir 315 salah? Di satu arah, itu adalah 315 derajat, di arah lain, itu 45. Anda ingin memilih mana yang terkecil dari 2 sudut yang mungkin dan ini tampaknya secara intrinsik memerlukan persyaratan. Anda tidak dapat menyelesaikannya dengan membungkus aritmatika (mis. Melalui operator modulus) karena ketika Anda secara bertahap meningkatkan satu sudut, sudut di antara mereka tumbuh hingga mencapai 180 dan kemudian mulai menurun.
Saya pikir Anda harus memeriksa kedua sudut dan memutuskan arah mana yang ingin Anda ukur, atau menghitung kedua arah dan memutuskan hasil mana yang Anda inginkan.
sumber
Selalu ada trik melakukan kedua cabang dan membiarkan hasil perbandingan memilih satu:
Saya tidak tahu cara untuk melakukannya tanpa perbandingan , tetapi biasanya cabang adalah apa yang membuat kode lambat dan panjang, bukan perbandingan. Setidaknya menurut saya, ini lebih mudah dibaca daripada jawaban Martin (setiap programmer C yang baik akan mengenalinya sebagai setara tanpa cabang dan melihat apa yang dilakukannya), tetapi juga kurang efisien.
Tapi seperti yang saya katakan di komentar saya, algoritma branchless bagus untuk prosesor dengan saluran pipa yang dalam dan prediksi yang buruk - mikrokontroler biasanya memiliki pipa kecil, dan PC desktop biasanya memiliki prediksi yang baik, jadi kecuali Anda menargetkan konsol game, versi percabangan kemungkinan rute terbaik jika mengurangi jumlah instruksi.
Seperti biasa, pembuatan profil - yang mungkin sesederhana penghitungan op untuk sistem Anda - akan memberi Anda jawaban nyata.
sumber
Dengan asumsi true evaluate to -1 dan false mengevaluasi to 0, dan '~', '&' dan '|' bitwise tidak , dan dan atau operator masing-masing, dan kami bekerja dengan aritmatika dua-pelengkap:
sumber
Bagaimana dengan ini?
Penambahan 360 ada untuk menghindari perbedaan negatif, karena modulo dari angka negatif mengembalikan hasil negatif. Maka Anda mendapatkan yang lebih kecil dari dua hasil yang mungkin.
Masih ada keputusan implisit, tetapi saya tidak tahu bagaimana menghindarinya. Pada dasarnya Anda membandingkan dua sudut dengan menghitung perbedaan searah jarum jam atau berlawanan arah jarum jam, dan tampaknya Anda secara eksplisit menginginkan yang lebih kecil dari dua perbedaan ini. Saya tidak tahu bagaimana mendapatkan hasil itu tanpa membandingkannya. Yaitu, tanpa menggunakan "abs", "min", "max" atau operator serupa.
sumber
Sementara pertanyaan Anda tidak merujuk mereka, saya akan bekerja pada asumsi bahwa pertanyaan perhitungan sudut Anda berasal dari keinginan untuk mengetahui sudut minimum antara dua vektor .
Perhitungan itu mudah. Dengan asumsi A dan B adalah vektor Anda:
angle_between = acos( Dot( A.normalized, B.normalized ) )
Jika Anda tidak memiliki vektor dan ingin menggunakan pendekatan ini, Anda bisa membuat vektor satuan panjang dengan sudut pandang Anda
new Vector2( cos( angle ), sin ( angle ) )
.sumber
Pada dasarnya sama dengan jawaban JasonD, kecuali menggunakan operasi bitwise bukan fungsi nilai absolut.
Ini dengan asumsi Anda memiliki bilangan bulat pendek 16-bit!
sumber
kupikir
sumber
Karena Anda hanya peduli tentang menghilangkan cabang dan operasi "kompleks" di luar aritmatika, saya akan merekomendasikan ini:
min(abs(angle1 - angle2), abs(angle2 - angle1))
Anda masih membutuhkan
abs
di sana meskipun semua sudut positif. Jika tidak, hasil paling negatif akan selalu dipilih (dan akan selalu ada tepat satu jawaban negatif untuk positif, unik, dan b ketika membandingkan ab dan ba).Catatan: Ini tidak akan mempertahankan arah antara angle1 dan angle2. Terkadang Anda membutuhkannya untuk tujuan AI.
Ini mirip dengan jawaban CeeJay, tetapi menghilangkan semua modulos. Saya tidak tahu berapa biaya siklusnya
abs
, tetapi saya akan menebak itu 1 atau 2. Sulit untuk mengatakan berapa biayanyamin
. Mungkin 3? Jadi bersama dengan 1 siklus per pengurangan, baris ini harus memiliki biaya sekitar 4 hingga 9.sumber
Dapatkan sudut relatif yang lebih kecil dalam formulir yang ditandatangani (+/-), dari perspektif miliki ke inginkan :
Derajat
Radian
Alasan
Saya menemukan utas ini setelah saya menemukan jawabannya, mencari solusi yang menghindari modulo; sejauh ini saya belum menemukannya . Solusi ini adalah untuk melestarikan tanda perspektif, ketika @ jacob-phillips menanyakan komentar ini . Ada solusi yang lebih murah jika Anda hanya membutuhkan sudut unsigned terpendek.
sumber
Ini pertanyaan lama tapi saya mengalami kasus yang sama - harus mendapatkan perbedaan sudut yang ditandatangani dan lebih disukai tanpa cabang dan matematika yang berat. Inilah yang akhirnya saya dapatkan:
Batasannya adalah bahwa 'b' tidak boleh memiliki lebih dari rotasi 'N' dibandingkan dengan 'a'. Jika Anda tidak dapat memastikannya dan dapat mengizinkan operasi tambahan, gunakan ini sebagai baris pertama:
Saya mendapat ide dari komentar ke-13 posting ini: http://blog.lexique-du-net.com/index.php?post/Calculate-the-real-difference-between-two-angles-keeping-the- tanda
sumber
saya kira saya bisa mengatakan
tentu saja, mengingat sudut diukur dalam derajat.
sumber