วิธีการคำนวณมุมที่มีเสถียรภาพของตัวเลขระหว่างเวกเตอร์


14

เมื่อใช้สูตรคลาสสิกสำหรับมุมระหว่างสองเวกเตอร์:

α=arccos⁡v1⋅v2‖v1‖‖v2‖

หนึ่งพบว่าสำหรับมุมเล็ก / เฉียบพลันมากมีการสูญเสียความแม่นยำและผลลัพธ์ไม่ถูกต้อง ดังที่อธิบายไว้ในคำตอบของ Stack Overflow คำตอบเดียวคือใช้อาร์กแทนเจนต์แทน:

α=arctan⁡2(‖v1×v2‖,v1⋅v2)

และสิ่งนี้ย่อมให้ผลลัพธ์ที่ดีกว่า อย่างไรก็ตามฉันสงสัยว่าสิ่งนี้จะให้ผลที่ไม่ดีกับมุมที่อยู่ใกล้กับπ/2หรือไม่ เป็นอย่างนั้นเหรอ? ถ้าเป็นเช่นนั้นมีสูตรใดที่จะคำนวณมุมอย่างแม่นยำโดยไม่ตรวจสอบความอดทนภายในifสาขาหรือไม่?


1
สิ่งนี้จะขึ้นอยู่กับการใช้งานฟังก์ชั่นแทนเจนต์ของพารามิเตอร์สองตัว รุ่นที่ช้าและเสถียรจะสลับอย่างมีเงื่อนไขระหว่างการทำงานกับ x / y และ y / x เพื่อรักษาความแม่นยำในขณะที่รุ่นที่รวดเร็วเพียงติดสิ่งต่าง ๆ ใน Quadrant ที่เหมาะสมและดังนั้นจึงไม่แม่นยำกว่ารุ่นพารามิเตอร์เดียว
— origimbo

คุณควรกำหนด "การสูญเสียของความแม่นยำ": คิดว่าคำตอบที่ถูกต้องคือαและคุณได้รับแทนα+Δ\ คุณต้องการΔ≪αหรือΔ≪πเพียงพอหรือไม่
— Stefano M

ในกรณีนี้คำตอบที่ถูกคือและฉันได้ทั้ง1 αα⋅108≪1
— astrojuanlu

คำตอบ:


18

( ฉันได้ทดสอบวิธีการนี้มาก่อนและฉันจำได้ว่าทำงานได้อย่างถูกต้อง แต่ฉันไม่ได้ทดสอบวิธีนี้โดยเฉพาะสำหรับคำถามนี้ )

เท่าที่ฉันจะบอกได้ทั้ง และสามารถทนทุกข์ทรมานจากการยกเลิกหายนะหากพวกเขาเกือบขนาน / ตั้งฉากกัน - atan2 ไม่สามารถให้ความแม่นยำที่ดีถ้าอินพุตปิด‖v1×v2‖v1⋅v2

เริ่มต้นโดยปรับโครงสร้างปัญหาใหม่เพื่อหามุมของสามเหลี่ยมที่มีความยาวด้าน,และ(สิ่งเหล่านี้คำนวณได้อย่างแม่นยำในการคำนวณเลขทศนิยม) มีสูตรที่เป็นที่รู้จักกันดีของนกกระสาเนื่องจาก Kahan (การคำนวณพื้นที่และมุมของสามเหลี่ยมคล้ายเข็ม ) ซึ่งช่วยให้คุณคำนวณพื้นที่และมุม (ระหว่างและ ) ของรูปสามเหลี่ยมที่ระบุโดยความยาวด้าน และทำอย่างเสถียรเชิงตัวเลข เนื่องจากการลดลงของปัญหาย่อยนี้มีความถูกต้องเช่นกันวิธีการนี้ควรใช้กับอินพุตที่กำหนดเองa=|v1|b=|v2|c=|v1−v2|ab

การอ้างถึงจากกระดาษนั้น (ดูหน้า 3) โดยสมมติว่า , วงเล็บทั้งหมดที่นี่ถูกวางไว้อย่างระมัดระวังและพวกมันสำคัญ; หากคุณพบว่าตัวเองกำลังหาสแควร์รูทของจำนวนลบความยาวด้านอินพุตนั้นไม่ใช่ความยาวด้านของสามเหลี่ยมa≥b

μ={c−(a−b),if b≥c≥0,b−(a−c),if c>b≥0,invalid triangle,otherwise
angle=2arctan⁡(((a−b)+c)μ(a+(b+c))((a−c)+b))

มีคำอธิบายวิธีการทำงานรวมถึงตัวอย่างของค่าที่สูตรอื่น ๆ ล้มเหลวในกระดาษของ Kahan สูตรแรกของคุณสำหรับคือในหน้า 4αC″

เหตุผลหลักที่ฉันแนะนำสูตรของ Kahan Heron ก็คือเพราะมันเป็นสูตรดั้งเดิมที่ดีมาก - คำถามเรขาคณิตเชิงระนาบจำนวนมากอาจลดลงเพื่อหาพื้นที่ / มุมของสามเหลี่ยมโดยพลการดังนั้นถ้าคุณสามารถลดปัญหาของคุณได้นั่นคือ เป็นสูตรที่เสถียรดีและไม่จำเป็นต้องคิดอะไรขึ้นมาเอง

แก้ไขความคิดเห็นของสเตฟาโนฉันทำพล็อตข้อผิดพลาดแบบสัมพัทธ์สำหรับ , ( รหัส ) สองบรรทัดคือข้อผิดพลาดสัมพัทธ์สำหรับและ ,จะไปตามแกนนอน ดูเหมือนว่ามันใช้งานได้ v1=(1,0)v2=(cos⁡θ,sin⁡θ)θ=ϵθ=π/2−ϵϵป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณสำหรับลิงค์และคำตอบ! น่าเสียดายที่สูตรที่สองที่ฉันเขียนไม่ปรากฏในบทความ ในทางกลับกันวิธีนี้อาจมีความซับซ้อนเล็กน้อยเนื่องจากต้องใช้การฉายภาพในแบบ 2D
— astrojuanlu

2
@astrojuanlu ไม่มีการฉายเป็น 2d ตรงนี้: ไม่ว่าเวกเตอร์ 3 มิติสองตัวใดก็ตามพวกมันนิยามสามเหลี่ยม (ระนาบ) เดี่ยวระหว่างพวกมัน - คุณแค่ต้องรู้ความยาวข้างของมัน
— คิริลล์

คุณพูดถูกแล้วความคิดเห็นของฉันไม่สมเหตุสมผล ฉันคิดในพิกัดแทนความยาว ขอบคุณอีกครั้ง!
— astrojuanlu

2
@astrojuanlu อีกสิ่งหนึ่งที่ฉันต้องการทราบ: ดูเหมือนว่ามีการพิสูจน์อย่างเป็นทางการว่าสูตรพื้นที่มีความถูกต้องในวิธีการคำนวณพื้นที่ของรูปสามเหลี่ยม: Revisit อย่างเป็นทางการ Sylvie Boldoใช้ Flocq
— คิริลล์

คำตอบที่ดี แต่ฉันโต้แย้งว่าคุณสามารถคำนวณในเลขทศนิยมได้อย่างถูกต้อง ในความเป็นจริงถ้าการยกเลิกการจองแล้วภัยพิบัติที่เกิดขึ้นในการคำนวณองค์ประกอบของ_2) cc<ϵ⋅min(a,b)(v1−v2)
— Stefano M

7

คำตอบที่มีประสิทธิภาพสำหรับคำถามนี้คือไม่น่าประหลาดใจเกินไปในบันทึกอื่นโดย Velvel Kahan :

α=2arctan⁡(‖v1‖v1‖+v2‖v2‖‖,‖v1‖v1‖−v2‖v2‖‖)

โดยที่ฉันใช้เป็นมุมที่สร้างโดยกับแกนนอน (คุณอาจต้องเรียงลำดับอาร์กิวเมนต์ในบางภาษา)arctan⁡(x,y)(x,y)

(ฉันให้การสาธิตMathematicaสูตร Kahan ที่นี่ )


คุณหมายถึง ? arctan⁡2
— astrojuanlu

1
ฉันคุ้นเคยกับการวาดอาร์กแทนเจนต์สองอาร์กิวเมนต์ในชื่อใช่ ในภาษาเช่น FORTRAN เทียบเท่าจะเป็น arctan⁡(x,y)ATAN2(Y, X)
— JM
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.