ไม่ว่าจะใช้ vincenty หรือ haversine หรือกฎหมายทรงกลมของ cosines มีภูมิปัญญาในการตระหนักถึงปัญหาที่อาจเกิดขึ้นกับรหัสที่คุณวางแผนที่จะใช้สิ่งที่ต้องระวังและบรรเทาและวิธีการจัดการกับ vincenty vs haversine vs sloc จะแตกต่างกันเมื่อเราตระหนักถึงปัญหาที่ซุ่มซ่อนของแต่ละคน / edgecases ซึ่งอาจหรืออาจไม่เป็นที่รู้จักแพร่หลาย โปรแกรมเมอร์ปรุงรสรู้เรื่องนี้ มือใหม่อาจไม่ได้ ฉันหวังว่าจะทำให้พวกเขาผิดหวังบางอย่างเมื่อตัวอย่างข้อมูลจากฟอรัมทำสิ่งที่ไม่คาดคิดในบางกรณี หากมีใครกำลังใช้รุ่นใดรุ่นหนึ่งอย่างจริงจังเช่น vincenty, haversine, sloc, SE, SO, Reddit, Quora ฯลฯ อาจให้ความช่วยเหลือที่ จำกัด ในการเขียนรหัสเริ่มต้นของโซลูชัน แต่นั่นไม่ได้หมายความว่า ทางออกหรือคำตอบที่ยอมรับได้นั้นไม่มีปัญหา หากโครงการมีความสำคัญมากพอโครงการนี้สมควรได้รับการวิจัยในปริมาณที่เหมาะสม อ่านคู่มืออ่านเอกสารและหากมีการตรวจสอบรหัสของรหัสนั้นให้อ่าน การคัดลอกและวางตัวอย่างหรือส่วนสำคัญที่ถูก upvoted เป็นร้อยเท่าหรือมากกว่านั้นไม่ได้หมายความว่าความปลอดภัยนั้นครอบคลุมและมั่นใจ
คำตอบที่น่าสนใจโพสต์โดย cffk ยกประเด็นของการตระหนักถึงซุ่มซ่อน edgecases ในการแก้ปัญหาการบรรจุที่สามารถผลิตข้อยกเว้นหรืออื่น ๆความยากลำบาก การอ้างสิทธิ์เฉพาะที่เกิดขึ้นในโพสต์นั้นเกินงบประมาณเวลาของฉันที่จะต้องดำเนินการในปัจจุบัน แต่ฉันได้รับจากการที่มีปัญหาที่ซุ่มซ่อนอยู่ในแพ็คเกจบางอย่างรวมถึงการใช้งาน vincenty อย่างน้อยหนึ่งเรื่อง ไม่ทางใดก็ทางหนึ่งเพื่อลดหรือขจัดความเสี่ยงในการเผชิญกับปัญหาเหล่านั้น ฉันจะไม่เพิ่มเพิ่มเติมในหัวข้อที่เกี่ยวข้องกับ vincenty (ไม่รู้ไกลเกินไป) แต่จะเปลี่ยนเป็น haversine อย่างน้อยในหัวข้อกับ OP
สูตร haversine ที่ได้รับการเผยแพร่อย่างแพร่หลายไม่ว่าจะเป็นภาษาไพ ธ อนหรือภาษาอื่นเพราะมันจะเป็นไปได้มากที่สุดที่จะใช้ IEEE 754 floating point spec ในทุกระบบ Intel และ Intel เหมือนกันทุกวันนี้และโปรเซสเซอร์ ARM, powerPC ฯลฯ จะมีความอ่อนไหวต่อข้อผิดพลาดยกเว้นที่หายาก แต่จริงและทำซ้ำได้มากใกล้หรือที่ระยะอาร์ค 180 องศาจุดตรงข้ามเนื่องจากการประมาณจุดลอยและการปัดเศษ มือใหม่บางคนอาจยังไม่ถูกสถานการณ์นี้กัด เนื่องจากข้อมูลจำเพาะของ fp นี้ประมาณและปัดเศษนี่ไม่ได้หมายความว่ารหัสใด ๆ ที่เรียกใช้ fp64 อาจทำให้เกิดข้อผิดพลาดในข้อยกเว้นไม่ใช่ แต่บางรหัส สูตรบางอย่างอาจไม่มี edgecases ที่ชัดเจนซึ่งการประมาณและการปัดเศษของ IEEE 754 fp64 อาจทำให้ค่าหลงทางเล็กน้อยจากโดเมนของวิธีการทางคณิตศาสตร์ที่คาดว่าจะประเมินค่าดังกล่าวอย่างไม่มีที่ติ ตัวอย่าง ... sqrt () หากค่าลบค้นหามาใน sqrt () เช่น sqrt (-0.00000000000000000122739) จะมีข้อผิดพลาดข้อยกเว้น ในสูตรแฮเวอรีนลักษณะที่มันไปสู่การแก้ปัญหามีสองวิธี sqrt () ใน atan2 () aที่คำนวณแล้วใช้ใน sqrt (), สามารถ, ที่จุด antipodal บนโลก, หลงทางเล็กน้อยต่ำกว่า 0.0 หรือสูงกว่า 1.0, เล็กน้อยมากเพราะ fp64 ประมาณและการปัดเศษ, ไม่ค่อย, แต่ทำซ้ำได้. การทำซ้ำที่เชื่อถือได้อย่างสม่ำเสมอในบริบทนี้ทำให้สิ่งนี้มีความเสี่ยงยกเว้นเป็น edgecase เพื่อปกป้องเพื่อบรรเทาแทนที่จะเป็นพยาธิใบไม้ที่แยกออกจากกันแบบสุ่ม นี่คือตัวอย่างสั้น ๆ ของ python3 ของ haversine โดยไม่มีการป้องกันที่จำเป็น:
import math as m
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
ใกล้หรือที่จุดตรงกันข้ามการคำนวณในบรรทัดแรกของสูตรอาจหลงทางลบไม่ค่อย แต่ทำซ้ำกับพิกัด lat lon เหล่านั้นซ้ำ ในการป้องกัน / แก้ไขเหตุการณ์ที่หายากหนึ่งก็สามารถเพิ่มหลังจากที่คำนวณเท่าที่เห็นด้านล่าง:
import math as m
note = ''
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
if a < 0.0: a = 0.0 ; note = '*'
if a > 1.0: a = 1.0 ; note = '**'
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
# note = '*' # a went below 0.0 and was normalized back to 0.0
# note = '**' # a went above 1.0 and was normalized back to max of 1.0
แน่นอนฉันไม่ได้แสดงฟังก์ชั่นทั้งหมดที่นี่ แต่ตัวอย่างสั้น ๆ ตามที่โพสต์บ่อย แต่อันนี้แสดงให้เห็นถึงการป้องกันสำหรับ sqrt () โดยการทดสอบa , และการทำให้เป็นมาตรฐานในกรณีที่จำเป็นนอกจากนี้ยังช่วยประหยัดความจำเป็นที่จะต้องใส่ทั้งสิ่งในลองยกเว้น note = '' ด้านบนคือการป้องกันไม่ให้สเตจ bytecode ทำการประท้วงโน้ตที่ใช้งานก่อนที่จะถูกกำหนดค่าถ้ามันถูกส่งคืนพร้อมกับผลลัพธ์ของฟังก์ชัน
กับการเปลี่ยนแปลงง่ายๆของการเพิ่มสองทดสอบ sqrt () ที่ฟังก์ชั่นจะมีความสุขและรหัสในขณะนี้มีการเพิ่มเติมทราบว่าสามารถกลับไปยังรหัสโทรแจ้งเตือนว่าผลที่ได้รับปกติเล็กน้อยและทำไม บางคนอาจสนใจบางคนอาจไม่ แต่มีมันเพื่อป้องกันข้อผิดพลาดข้อยกเว้นว่า 'สามารถ' เกิดขึ้นเป็นอย่างอื่น ลองยกเว้นบล็อกอาจตรวจจับข้อยกเว้น แต่ไม่สามารถแก้ไขได้เว้นแต่จะเขียนอย่างชัดเจนให้ทำ มันดูเหมือนง่ายต่อการรหัสสายการแก้ไข (s) ทันทีหลังจากที่สายการคำนวณ การป้อนข้อมูลที่ขัดอย่างละเอียดแล้วไม่ควรต้องลองยกเว้นบล็อกที่นี่เลย
สรุปถ้าใช้ haversine, รหัสอย่างชัดเจนมากกว่าการใช้แพคเกจหรือไลบรารีไม่ว่าภาษาของคุณเลือกมันจะเป็นความคิดที่ดีในการทดสอบและการที่จะปรับกลับเข้ามาในช่วงที่จำเป็น 0.0 <= a <= 1.0 ในการสั่งซื้อ เพื่อป้องกันบรรทัดถัดไปด้วยการคำนวณc แต่ตัวอย่างโค้ด haversine ส่วนใหญ่ไม่แสดงและไม่พูดถึงความเสี่ยง
ประสบการณ์: ระหว่างการทดสอบอย่างละเอียดทั่วโลกเพิ่มขึ้น 0.001 องศาฉันได้เติมฮาร์ดไดรฟ์ที่มีชุด lat lon ซึ่งทำให้เกิดข้อยกเว้นเป็นข้อยกเว้นที่เชื่อถือได้ซ้ำ ๆ กันที่เชื่อถือได้ในระหว่างเดือนของการทดสอบความน่าเชื่อถือของ CPU แฟนและความอดทนของฉัน ใช่ฉันได้ลบบันทึกส่วนใหญ่ไปแล้วเนื่องจากวัตถุประสงค์ของพวกเขาส่วนใหญ่เพื่อพิสูจน์ประเด็น (ถ้าอนุญาตให้เล่นสำนวน) แต่ฉันมีบันทึกสั้น ๆ ของ 'ปัญหาค่า lat lon' ที่เก็บไว้เพื่อการทดสอบ
ความแม่นยำ: ผลลัพธ์aและ haversine ทั้งหมดจะสูญเสียความถูกต้องบางส่วนโดยการทำให้ค่ากลับคืนสู่ระดับโดเมนเล็กน้อย ไม่มากอาจไม่มากไปกว่าการประมาณ fp64 และการปัดเศษที่แนะนำแล้วซึ่งทำให้โดเมนนั้นลอยไปเล็กน้อย หากคุณพบว่า haversine ยอมรับได้ใน vincenty แล้ว - ง่ายกว่าเร็วกว่าง่ายกว่าที่จะปรับแต่งแก้ไขและบำรุงรักษา haversine อาจเป็นทางออกที่ดีสำหรับโครงการของคุณ
ฉันใช้ haversine บน skysphere ที่ฉายอยู่เหนือศีรษะเพื่อวัดระยะเชิงมุมระหว่างวัตถุในท้องฟ้าเมื่อมองจากตำแหน่งบนโลกการทำแผนที่ azimuth และ alt เป็นพิกัดเทียบเท่ากับ skysphere lat lon ไม่มี elipsoid เลยแม้แต่น้อย skysphere เชิงทฤษฎีที่คาดการณ์ไว้เป็นทรงกลมที่สมบูรณ์แบบเมื่อมันมาถึงการวัดระยะทางเชิงมุมมองมุมระหว่างวัตถุทั้งสองจากตำแหน่งบนพื้นผิวโลก มันเหมาะกับความต้องการของฉันอย่างสมบูรณ์แบบ ดังนั้น haversine ยังคงมีประโยชน์อย่างมากและแม่นยำมากในบางแอปพลิเคชั่น (ในจุดประสงค์ของฉัน) ... แต่ถ้าคุณใช้มันไม่ว่าจะบน GIS หรือการนำทางบนโลกหรือในการสังเกตและวัดวัตถุท้องฟ้า ในกรณีที่มีการจุดตรงกันข้ามกับเท้าหรือจุดใกล้มากตรงกันข้ามกับเท้าโดยการทดสอบและเขยิบมันกลับเข้าไปในโดเมนที่ต้องการเมื่อจำเป็น
haversine ที่ไม่มีการป้องกันนั้นมีอยู่ทั่วอินเทอร์เน็ตและฉันเพิ่งเห็นโพสต์ Usenet เก่า ๆ ที่แสดงการป้องกันบางอย่างฉันคิดว่าจากใครบางคนที่ JPL และนั่นอาจเป็น pre-1985 ปีก่อน IEEE 754 จุดลอยตัว spec อีกสองหน้าพูดถึงปัญหาที่อาจเกิดขึ้นใกล้กับจุดตรงกันข้าม แต่ไม่ได้อธิบายถึงปัญหาเหล่านั้น ดังนั้นจึงมีความกังวลสำหรับมือใหม่ (เช่นฉัน) ที่อาจไม่เข้าใจการฝึกฝนที่ดีพอที่จะทำการวิจัยเพิ่มเติมและทดสอบ edgecases ซึ่งเป็นรหัสที่พวกเขาคัดลอกและวางลงในโครงการที่ไว้ใจได้ โพสต์ที่น่าสนใจของ cffk ได้รับการรีเฟรชว่าเป็นปัญหาสาธารณะประเภทนี้ซึ่งไม่ได้กล่าวถึงบ่อยครั้งและไม่ได้รับการเข้ารหัสในที่สาธารณะเพื่อป้องกันตัวอย่างและไม่ค่อยมีการพูดถึงในลักษณะนี้เมื่อเทียบกับจำนวนรุ่นที่ไม่มีการป้องกัน
ในปี 20190923 หน้าวิกิสำหรับสูตรแฮเวอรีนไม่ได้กล่าวถึงปัญหาที่เป็นไปได้ที่จุดตรงข้ามเนื่องจากปัญหาจุดลอยตัวในอุปกรณ์คอมพิวเตอร์ ... สนับสนุน ...
https://en.wikipedia.org/wiki/Haversine_formula
(เนื่องจากหน้าวิกินั้นไม่มีในขณะนี้มีตัวยึด html สำหรับส่วนที่ฉันจะเชื่อมโยงโดยตรงดังนั้นหลังจากโหลดหน้าเว็บแล้วให้ทำการค้นหาในหน้าเบราว์เซอร์นั้นสำหรับ 'เมื่อใช้สูตรเหล่านี้' และคุณจะ ดูปัญหาของแฮเวอรีนที่มีการกล่าวถึงสิ่งที่ตรงกันข้ามกับ antipodal อย่างเป็นทางการมากขึ้น)
และไซต์อื่น ๆ นี้ยังมีการกล่าวถึงสั้น ๆ :
https://www.movable-type.co.uk/scripts/latlong.html
หากมีการค้นหาในหน้าสำหรับ 'รวมถึงการป้องกันการปัดเศษข้อผิดพลาด' มีสิ่งนี้ ...
หาก atan2 ไม่พร้อมใช้งาน c สามารถคำนวณได้จาก 2 ⋅ asin (ขั้นต่ำ (1, √a)) (รวมถึงการป้องกันข้อผิดพลาดในการปัดเศษ)
ขณะนี้มีอินสแตนซ์ที่หายากซึ่งมีการกล่าวถึงข้อผิดพลาดในการปัดเศษและการป้องกันแสดงสำหรับเวอร์ชัน asin () แต่ยังไม่ได้กล่าวถึงหรือแสดงสำหรับรุ่น atan2 () แต่อย่างน้อยก็มีการกล่าวถึงความเสี่ยงของข้อผิดพลาดในการปัดเศษ
imho แอปพลิเคชัน 24/7/365 ใด ๆ ที่ใช้ haversine ต้องการการปกป้องใกล้กับจุด antipodal ในรายละเอียดที่สำคัญและเรียบง่าย
ฉันไม่ทราบว่าแพคเกจ haversine ใดที่มีหรือไม่มีการป้องกันนี้ แต่ถ้าคุณยังใหม่กับสิ่งนี้ทั้งหมดและคุณจะใช้เวอร์ชัน 'snippet' ที่เผยแพร่อย่างแพร่หลายตอนนี้คุณรู้แล้วว่ามันต้องการการป้องกันและ การป้องกันนั้นง่ายมากที่จะติดตั้งนั่นคือถ้าคุณไม่ได้ใช้ vincenty และไม่ใช้ haversine ที่ทำแพคเกจโดยไม่ต้องเข้าถึงรหัสของแพคเกจ
IOW ไม่ว่าจะใช้ vincenty หรือ haversine หรือ sloc เราควรตระหนักถึงปัญหาใด ๆ เกี่ยวกับรหัสสิ่งที่ต้องระวังและบรรเทาและวิธีการจัดการกับปัญหา vincenty vs haversine vs sloc จะแตกต่างกันเมื่อเราตระหนักถึงแต่ละคน ปัญหาที่ซุ่มซ่อน / edgecases ซึ่งอาจหรืออาจไม่เป็นที่รู้จักแพร่หลาย