ความแตกต่างระหว่างการคำนวณระยะทางของ Vincenty กับ Great Circle หรือไม่?


16

งูใหญ่แพคเกจ geopyมีสองวัดระยะทางเทคนิค: เกรทเซอร์เคิและVincenty ของสูตร

>>> from geopy.distance import great_circle
>>> from geopy.distance import vincenty
>>> p1 = (31.8300167,35.0662833) # (lat, lon) - https://goo.gl/maps/TQwDd
>>> p2 = (31.8300000,35.0708167) # (lat, lon) - https://goo.gl/maps/lHrrg
>>> vincenty(p1, p2).meters
429.16765838976664
>>> great_circle(p3, p4).meters
428.4088367903001

อะไรคือความแตกต่าง? ต้องการการวัดระยะทางแบบใด

คำตอบ:


18

ตามที่ Wikipedia สูตรของ Vincenty นั้นช้ากว่า แต่มีความแม่นยำมากกว่า :

สูตรของ Vincenty เป็นวิธีการวนซ้ำสองแบบที่เกี่ยวข้องซึ่งใช้ในหน่วยพื้นที่เพื่อคำนวณระยะห่างระหว่างจุดสองจุดบนพื้นผิวของทรงกลมที่พัฒนาโดยแธดเดียส มีความแม่นยำมากกว่าวิธีการเช่นระยะทางวงกลมใหญ่ซึ่งถือว่าโลกเป็นทรงกลม

ความแตกต่างของความแม่นยำอยู่~0.17%ในระยะทาง 428 เมตรในอิสราเอล ฉันได้ทำการทดสอบความเร็วที่รวดเร็วและสกปรกแล้ว:

<class 'geopy.distance.vincenty'>       : Total 0:00:04.125913, (0:00:00.000041 per calculation)
<class 'geopy.distance.great_circle'>   : Total 0:00:02.467479, (0:00:00.000024 per calculation)

รหัส:

import datetime
from geopy.distance import great_circle
from geopy.distance import vincenty
p1 = (31.8300167,35.0662833)
p2 = (31.83,35.0708167)

NUM_TESTS = 100000
for strategy in vincenty, great_circle:
    before = datetime.datetime.now()
    for i in range(NUM_TESTS):
        d=strategy(p1, p2).meters
    after = datetime.datetime.now()
    duration = after-before
    print "%-40s: Total %s, (%s per calculation)" % (strategy, duration, duration/NUM_TESTS)

เพื่อสรุป:สูตรของ Vincenty นั้นเพิ่มขึ้นเป็นสองเท่าของเวลาการคำนวณเมื่อเทียบกับวงกลมใหญ่และความแม่นยำเพิ่มขึ้นเมื่อถึงจุดทดสอบคือ ~ 0.17%

เนื่องจากเวลาในการคำนวณมีน้อยมากสูตรของ Vincenty จึงเป็นที่ต้องการสำหรับทุกความต้องการใช้งานจริง

ปรับปรุง : ตามความเห็นที่ชาญฉลาดโดยwhuberและcffk 's และcffk ' s คำตอบผมยอมรับว่ากำไรจากความถูกต้องควรจะนำมาเปรียบเทียบกับข้อผิดพลาดที่ไม่ได้วัด ดังนั้นสูตรของ Vincenty จึงมีความแม่นยำน้อยกว่าไม่ใช่ 0.17%


3
+1 ทำได้ดีมาก สำหรับการวิเคราะห์ทั่วไปของข้อผิดพลาดข้ามโลกโปรดดูที่หัวข้อที่gis.stackexchange.com/questions/25494
whuber

3
Vincenty คำนวณระยะทางมาตรวิทยาวงรีวงรีที่แม่นยำกว่าสูตรวงกลมใหญ่หลายเท่า ดังนั้นการบอกว่าการเพิ่มความแม่นยำของ Vincenty แค่ 0.17% นั้นทำให้เข้าใจผิด (เทียบเท่ากับการบอกว่าเลขคณิตความแม่นยำสองเท่านั้นมีความแม่นยำมากกว่า 0.1% มากกว่าการใช้กฎสไลด์)
cffk

14

หากคุณใช้ geopy ระยะทาง great_circle และ vincenty ก็สะดวกสบายเท่า ๆ กัน ในกรณีนี้คุณควรใช้อันที่ให้ผลลัพธ์ที่แม่นยำมากขึ้นเช่น vincenty ข้อควรพิจารณาสองข้อ (ตามที่คุณระบุ) คือความเร็วและความแม่นยำ

Vincenty ช้ากว่าสองเท่า แต่ในแอพพลิเคชันจริงอาจทำให้เวลาใช้งานที่เพิ่มขึ้นนั้นเล็กน้อย แม้ว่าแอปพลิเคชันของคุณจะเรียกการคำนวณระยะทางหนึ่งล้านครั้งเรากำลังพูดถึงความแตกต่างในเวลาไม่กี่วินาที

สำหรับจุดที่คุณใช้ข้อผิดพลาดใน vincenty คือ 6 μmและข้อผิดพลาดในระยะทางวงกลมใหญ่คือ 0.75 m จากนั้นฉันจะบอกว่า vincenty มีความแม่นยำมากกว่า 120000 เท่า (มากกว่าที่แม่นยำมากกว่า 0.17%) สำหรับจุดทั่วไปข้อผิดพลาดในระยะทางวงกลมใหญ่สามารถมากถึง 0.5% คุณสามารถอยู่กับข้อผิดพลาด 0.5% ในระยะทางได้หรือไม่? สำหรับการใช้งานทั่วไป (ระยะทางจากเคปทาวน์ไปยังไคโรคือเท่าไหร่) คุณน่าจะทำได้ อย่างไรก็ตามแอปพลิเคชัน GIS จำนวนมากมีข้อกำหนดด้านความแม่นยำที่เข้มงวดกว่ามาก (0.5% คือ 5 ม. เกิน 1 กม. ซึ่งสร้างความแตกต่างอย่างแท้จริง)

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

ADDENDUM (พฤษภาคม 2560)

ในการตอบกลับคำตอบที่ได้รับจาก @ craig-hicks วิธี vincenty () ใน geopy มีข้อบกพร่องร้ายแรงที่อาจทำให้เกิดข้อผิดพลาดสำหรับคะแนน antipodal เกือบ เอกสารในรหัสแนะนำการเพิ่มจำนวนการวนซ้ำ แต่นี่ไม่ใช่วิธีการแก้ปัญหาทั่วไปเนื่องจากวิธีการวนซ้ำที่ใช้โดย vincenty () ไม่เสถียรสำหรับจุดดังกล่าว (การวนซ้ำแต่ละครั้งจะนำคุณไปไกลจากการแก้ไขที่ถูกต้อง)

เหตุใดฉันจึงอธิบายลักษณะของปัญหาว่า "อาจถึงแก่ชีวิต" เนื่องจากการใช้ฟังก์ชั่นระยะทางภายในห้องสมุดซอฟต์แวร์อื่นจำเป็นต้องสามารถจัดการกับข้อยกเว้นได้ การจัดการโดยการคืน NaN หรือระยะทางวงกลมใหญ่อาจไม่เป็นที่น่าพอใจเนื่องจากฟังก์ชันระยะทางที่เกิดขึ้นจะไม่เชื่อฟังความไม่เท่าเทียมกันของรูปสามเหลี่ยมซึ่งขัดขวางการใช้งานเช่นในต้นไม้ vantage-point

สถานการณ์ไม่เยือกเย็นอย่างสมบูรณ์ แพคเกจทางภูมิศาสตร์ของฉันหลาม คำนวณระยะทางมาตราส่วนอย่างถูกต้องโดยไม่มีความล้มเหลวใด ๆ geopy ดึงคำขอ # 144การเปลี่ยนแปลงการทำงานระยะ geopy ของแพคเกจการใช้งาน geographiclib ถ้ามันใช้ได้ น่าเสียดายที่คำขอถอนเงินนี้ได้รับการแจ้งเตือนตั้งแต่เดือนสิงหาคม 2559

ADDENDUM (พฤษภาคม 2018)

ขณะนี้ geopy 1.13.0 ใช้แพ็คเกจทางภูมิศาสตร์สำหรับการคำนวณระยะทาง นี่คือตัวอย่างการโทร (ตามตัวอย่างในคำถามเดิม):

>>> from geopy.distance import great_circle
>>> from geopy.distance import geodesic
>>> p1 = (31.8300167,35.0662833) # (lat, lon) - https://goo.gl/maps/TQwDd
>>> p2 = (31.8300000,35.0708167) # (lat, lon) - https://goo.gl/maps/lHrrg
>>> geodesic(p1, p2).meters
429.1676644986777
>>> great_circle(p1, p2).meters
428.28877358686776

3

คำขอโทษของฉันสำหรับการโพสต์คำตอบที่สองที่นี่ แต่ฉันใช้โอกาสที่จะตอบสนองต่อการร้องขอโดย @ craig-hicks เพื่อให้ความถูกต้องและการเปรียบเทียบเวลาสำหรับอัลกอริทึมต่างๆสำหรับการคำนวณระยะทางธรณีวิทยา การถอดความความคิดเห็นที่ฉันทำกับคำขอดึงของฉัน# 144สำหรับ geopy ซึ่งอนุญาตให้ใช้หนึ่งในสองของการใช้อัลกอริทึมของฉันสำหรับ geodesics ที่จะใช้ภายใน geopy หนึ่งคือการ ดำเนินการหลามพื้นเมือง geodesic (geographiclib)และการใช้อื่น ๆการดำเนินงานใน C, เนื้อที่ (pyproj)

นี่คือข้อมูลเวลาบางส่วน เวลาเป็นไมโครวินาทีต่อการโทร

method                          dist    dest
geopy great_circle              20.4    17.1
geopy vincenty                  40.3    30.4
geopy geodesic(pyproj)          37.1    31.1
geopy geodesic(geographiclib)  302.9   124.1

นี่คือความถูกต้องของการคำนวณเนื้อที่อยู่บนพื้นฐานของฉัน ชุดทดสอบ Geodesic ข้อผิดพลาดมีหน่วยเป็นไมครอน (1e-6 m)

method                        distance destination
geopy vincenty                 205.629  141.945
geopy geodesic(pyproj)           0.007    0.013
geopy geodesic(geographiclib)    0.011    0.010

ฉันได้รวมคำขอการดึงของฮันโนส# 194ซึ่งแก้ไขข้อบกพร่องที่ไม่ดีในฟังก์ชั่นปลายทาง หากไม่มีการแก้ไขนี้ข้อผิดพลาดในการคำนวณปลายทางสำหรับ vincenty คือ 8.98 เมตร

19.2% ของการทดสอบล้มเหลวด้วย vincenty.distance (การวนซ้ำ = 20) อย่างไรก็ตามชุดทดสอบจะเอียงไปทางเคสซึ่งจะทำให้กรณีนี้ล้มเหลว

ด้วยจุดสุ่มบนวงรี WGS84 อัลกอรึทึมของ Vincenty รับประกันว่าจะล้มเหลว 16.6 จาก 1000000 ครั้ง (การแก้ปัญหาที่ถูกต้องคือจุดคงที่ที่ไม่แน่นอนของวิธีการของ Vincenty)

ด้วยการประยุกต์ใช้ geopy ของ Vincenty and iterations = 20 อัตราความล้มเหลวคือ 82.8 ต่อ 1000000 กับ iterations = 200 อัตราความล้มเหลวคือ 21.2 ต่อ 1000000

แม้ว่าอัตราเหล่านี้จะมีขนาดเล็ก แต่ความล้มเหลวก็เป็นเรื่องปกติ ตัวอย่างเช่นในชุดข้อมูลของ 1,000 จุดสุ่ม (คิดว่าสนามบินโลกบางที) การคำนวณเมทริกซ์ทางไกลเต็มรูปแบบจะล้มเหลวโดยเฉลี่ย 16 ครั้ง (ด้วยการวนซ้ำ = 20)


2

ดูเหมือนว่าแพ็คเกจ geopy.distance มีฟังก์ชัน "distance ()" ซึ่งมีค่าเริ่มต้นเป็น vincenty () ฉันขอแนะนำให้ใช้ระยะทาง () ตามหลักการเนื่องจากเป็นคำแนะนำแพ็คเกจในกรณีที่แตกต่างจาก vincenty () ในอนาคต (ไม่น่าจะเป็นเช่นนั้น) อ่านต่อไป:

หมายเหตุเอกสารนี้มีอยู่ในซอร์สโค้ดสำหรับฟังก์ชัน vincenty () ที่คุณระบุ:

หมายเหตุ: การใช้งานของระยะทาง Vincenty นี้ไม่สามารถมาบรรจบกันสำหรับจุดที่ถูกต้อง ในบางกรณีผลลัพธ์สามารถรับได้โดยเพิ่มจำนวนการวนซ้ำ ( iterationsอาร์กิวเมนต์คำหลักที่กำหนดในคลาส__init__ด้วยค่าเริ่มต้นเท่ากับ 20) อาจใช้งานได้ดีกว่า: class: .great_circleซึ่งมีความแม่นยำน้อยกว่าเล็กน้อย แต่ให้ผลลัพธ์เสมอ

รหัสที่มากับ TH เหนือความเห็น / หมายเหตุสามารถพบได้ที่ https://github.com/geopy/geopy/blob/master/geopy/distance.py เลื่อนลงไปคำนิยามสำหรับ vincenty ()

อย่างไรก็ตามฟังก์ชั่นระยะทางเริ่มต้นที่ใช้โดยแพคเกจนั้นเมื่อระยะทาง caliing () เป็นฟังก์ชั่น vincenty () ซึ่งหมายถึงความล้มเหลวที่จะมาบรรจบกันไม่ได้เป็นหายนะและคำตอบที่เหมาะสมจะถูกส่งกลับ - ที่สำคัญที่สุดคือ

อัปเดต: ตามที่ระบุไว้โดย "cffk" ฟังก์ชัน vincenty () จะโยนข้อยกเว้น ValueError อย่างชัดเจนเมื่ออัลกอริทึมไม่ได้มาบรรจบกัน - แม้ว่าจะไม่ได้บันทึกไว้ในคำอธิบายฟังก์ชัน ดังนั้นเอกสารเป็นรถ


ไม่วิธี vincenty () สามารถสร้างข้อยกเว้น มันมักจะอ้างว่าสิ่งนี้ไม่สำคัญเพราะจะมีผลเฉพาะกับการคำนวณระยะทางระหว่างคะแนน antipodal เกือบ อย่างไรก็ตามความล้มเหลวดังกล่าวหมายความว่าความไม่เท่าเทียมกันของสามเหลี่ยมล้มเหลวดังนั้นระยะทาง Vincenty จึงไม่สามารถนำมาใช้ในการค้นหาเพื่อนบ้านที่ใกล้ที่สุดโดยใช้ต้นไม้ vantage-point (ซึ่งจะช่วยให้คุณกำหนดตัวอย่างเช่นตำแหน่งของสนามบินที่ใกล้ที่สุดอย่างมีประสิทธิภาพ) หากต้องการแก้ไขปัญหานี้คุณสามารถใช้คำขอดึงข้อมูลทางภูมิศาสตร์นี้github.com/geopy/geopy/pull/144ซึ่งใช้ GeographicLib เป็นระยะทาง
cffk

@cffk - ฉันไม่สามารถแยกแยะความมั่นใจจากความคิดเห็นหรือลิงก์ของคุณได้ แต่ฉันเดาว่า "คำขอการดึงข้อมูลภูมิศาสตร์" อาจเป็นตารางการค้นหา - ใช่ไหม การสนทนาสามารถแบ่งออกเป็นสองกรณี: กรณีที่ตารางการค้นหาไม่พร้อมใช้งาน (ดาวน์โหลด) และกรณีที่มีอยู่
Craig Hicks

@cffk - ในกรณีที่ไม่พร้อมใช้งาน: ประการแรกเอกสารเป็นรถเป็นหลักเพราะมันไม่ได้รวมถึงคำอธิบายของข้อยกเว้นตามแผน (ยก ValueError ("สูตร Vincenty ล้มเหลวในการบรรจบกัน!")) แต่ยังเพราะ มันไม่ได้อธิบายถึงความไม่เสถียรที่เกิดขึ้นที่การวัดจุดเกือบจะตรงกันข้าม ฉันอยากจะแนะนำให้เพิ่มฟังก์ชั่น vincenty_noexcpt ให้กับคลาส Vincenty ซึ่งจับข้อยกเว้นภายในและส่งกลับค่าวงกลมที่ยอดเยี่ยมแทนและทำให้การตั้งค่าเริ่มต้น: distance = vincenty_noexcep
Craig Hicks

@cffk - ในกรณีที่มีตารางการค้นหา: ฉันจะแนะนำการทดสอบและกำหนดเวลาเป็นจำนวนมากเพราะวิธีการค้นหามักจะออกนอกแคชและเวลาแพง การแทนที่วิธี vincenty ด้วยวิธี "pull" เป็นค่าเริ่มต้นอาจหมายความว่าทุกคนที่ดาวน์โหลดแพ็คเกจ "pull" ในไดเรกทอรี python จะเปลี่ยนการโทรที่มีอยู่ทั้งหมดเป็น vincenty เป็นการโทรเพื่อดึง - ซึ่งอาจเป็นปัญหาหากผู้ใช้จริงๆเพียงแค่ ต้องการลองใช้วิธี "ดึง" อย่างรอบคอบและชัดเจน
Craig Hicks

@ craig-hicks - ไม่ "คำขอการดึง" แทนที่อัลกอริทึมที่ดีกว่า (โดยฉัน!) สำหรับการวัดระยะทางดูdoi.org/10.1007/s00190-012-0578-zนี่ถูกต้องกว่า Vincenty เสมอส่งกลับผลลัพธ์เสมอ และใช้เวลาประมาณเดียวกัน ฉันไม่ใช่ผู้ดูแลระบบของ geopy และคำขอการดึงนี้ไม่ได้รับการติดตามตั้งแต่เดือนสิงหาคมปีที่แล้ว หากฉันมี druthers ของฉันสิ่งนี้จะถูกแทนที่เป็น geopy (และ vincenty () จะเรียกอัลกอริทึมใหม่แทนของ Vincenty) และนั่นจะเป็นการสิ้นสุดของการอภิปราย
cffk

1

ไม่ว่าจะใช้ 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 ซึ่งอาจหรืออาจไม่เป็นที่รู้จักแพร่หลาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.