Cho dù sử dụng vincenty hay haversine hay luật hình cầu của vũ trụ, sẽ có sự khôn ngoan trong việc nhận thức được bất kỳ vấn đề tiềm ẩn nào với mã mà bạn dự định sử dụng, những điều cần chú ý và giảm thiểu, và cách người ta đối phó với các vấn đề vincenty vs haversine và sloc sẽ khác nhau khi người ta nhận thức được các vấn đề / edgecase của mỗi người, có thể hoặc không được biết đến phổ biến. Các lập trình viên dày dạn biết điều này. Người mới có thể không. Tôi hy vọng sẽ giải phóng một số trong số họ thất vọng khi một đoạn trích từ một diễn đàn làm điều gì đó bất ngờ, trong một số trường hợp nhất định. Nếu một người nghiêm túc sẽ sử dụng một số phiên bản của bất kỳ trong số này, vincenty, haversine, sloc, thì SE, SO, Reddit, Quora, v.v., có thể đã cung cấp trợ giúp hạn chế trong một số mã hóa ban đầu của một giải pháp, nhưng điều đó không có nghĩa là giải pháp của họ hoặc được chấp nhận 'câu trả lời' là không có vấn đề. Nếu một dự án đủ quan trọng, nó xứng đáng với một lượng nghiên cứu hợp lý thích hợp. Đọc hướng dẫn, đọc tài liệu và nếu đánh giá mã của mã đó tồn tại, hãy đọc nó. Sao chép và dán đoạn trích hoặc ý chính được nâng cấp hàng trăm lần trở lên không có nghĩa là sự an toàn của nó là toàn diện và được đảm bảo.
Câu trả lời hấp dẫn được đăng bởi cffk nêu lên quan điểm nhận thức về việc ẩn giấu các edgecase, trong các giải pháp đóng gói, có thể tạo ra ngoại lệ hoặc những khó khăn khác . Các yêu cầu cụ thể được đưa ra trong bài đăng đó vượt quá ngân sách thời gian của tôi để theo đuổi hiện tại, nhưng tôi nhận thấy rằng có những vấn đề thực sự ẩn giấu trong các gói nhất định, bao gồm ít nhất một triển khai vincenty, trong đó ít nhất một người đã đề xuất cải thiện Bằng cách này hay cách khác, để giảm thiểu hoặc loại bỏ nguy cơ gặp phải những khó khăn đó. Tôi sẽ không thêm vào chủ đề đó liên quan đến vincenty (vì quá thờ ơ với nó), nhưng sẽ chuyển sang haversine, ít nhất là một phần về chủ đề với OP.
Công thức haversine được xuất bản phổ biến, dù bằng ngôn ngữ python hay ngôn ngữ khác, bởi vì nó rất có thể sẽ sử dụng thông số dấu phẩy động IEEE 754 trên hầu hết tất cả các hệ thống giống như intel và intel hiện nay, và bộ xử lý ARM, powerPC, v.v. cũng dễ bị các lỗi ngoại lệ hiếm gặp nhưng có thể lặp lại rất gần hoặc ở khoảng cách vòng cung 180 độ, các điểm đối cực, do các xấp xỉ điểm nổi và làm tròn. Một số người mới có thể chưa bị cắn bởi tình huống này. Bởi vì thông số fp này gần đúng và làm tròn, điều này không có nghĩa là bất kỳ mã nào gọi trên fp64 đều có thể gây ra lỗi ngoại lệ, không. Nhưng một số mã, một số công thức có thể không quá rõ ràng trong đó các phép tính gần đúng và làm tròn của IEEE 754 fp64 có thể khiến giá trị đi lạc ra khỏi miền của một phương pháp toán học được dự đoán sẽ đánh giá hoàn hảo giá trị đó. Một ví dụ ... sqrt (). Nếu một giá trị âm tìm đường vào sqrt (), chẳng hạn như sqrt (-0.00000000000000000122739), sẽ có một lỗi ngoại lệ. Trong công thức haversine, cách thức mà nó tiến tới một giải pháp, có hai phương thức sqrt () trong atan2 (). Cáca được tính toán và sau đó được sử dụng trong sqrt (), có thể, tại các điểm đối cực trên địa cầu, hơi đi lạc dưới 0,0 hoặc trên 1,0, rất ít vì xấp xỉ fp64 và làm tròn, nhưng hiếm khi lặp lại. Độ lặp lại đáng tin cậy nhất quán, trong bối cảnh này, làm cho điều này trở thành một rủi ro ngoại lệ, một edgecase để bảo vệ, để giảm thiểu, thay vì một con sán ngẫu nhiên bị cô lập. Đây là một ví dụ về một đoạn ngắn python3 của haversine, mà không có sự bảo vệ cần thiết:
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
Rất gần hoặc tại các điểm đối cực, một tính toán trong dòng đầu tiên của công thức có thể đi lạc âm, hiếm khi, nhưng lặp lại với các tọa độ lat lon tương tự. Để bảo vệ / sửa những lần xuất hiện hiếm hoi, người ta có thể dễ dàng thêm, sau khi một tính toán, như bên dưới:
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
Tất nhiên tôi đã không hiển thị toàn bộ chức năng ở đây, nhưng một đoạn ngắn như thường được đăng. Nhưng điều này cho thấy sự bảo vệ cho sqrt (), bằng cách kiểm tra a và bình thường hóa nó nếu cần thiết, cũng tiết kiệm nhu cầu đưa toàn bộ vào thử ngoại trừ. Ghi chú = '' lên trên cùng là để ngăn giai đoạn mã byte phản đối ghi chú đó đang được sử dụng trước khi được gán một giá trị, nếu nó được trả về với kết quả của hàm.
Với sự thay đổi đơn giản này, thêm hai một bài kiểm tra, các sqrt () chức năng sẽ được hạnh phúc, và mã ngay bây giờ có thêm lưu ý rằng có thể được trả lại cho gọi mã, để cảnh báo rằng kết quả đã bị bình thường một chút, và tại sao. Một số có thể quan tâm, một số có thể không, nhưng ở đó, ngăn ngừa một lỗi ngoại lệ, điều đó 'có thể' xảy ra. Một thử ngoại trừ khối có thể bắt ngoại lệ, nhưng không sửa nó, trừ khi được viết rõ ràng để làm như vậy. Có vẻ như dễ dàng hơn để mã dòng chỉnh (s) ngay lập tức sau khi một dòng tính toán. Đầu vào được kiểm tra kỹ lưỡng nên sau đó không yêu cầu thử ngoại trừ khối ở đây.
Nói tóm lại, nếu sử dụng haversine, mã hóa một cách rõ ràng hơn là sử dụng một gói phần mềm hoặc thư viện, không có vấn đề ngôn ngữ của bạn lựa chọn, nó sẽ là một ý tưởng tốt để thử nghiệm và để bình thường hóa một trở lại vào trong phạm vi cần thiết của 0.0 <= a <= 1.0 theo thứ tự để bảo vệ dòng tiếp theo với c tính toán . Nhưng phần lớn các đoạn mã haversine không hiển thị nó và không đề cập đến rủi ro.
Kinh nghiệm: trong quá trình kiểm tra kỹ lưỡng trên toàn cầu, với mức tăng 0,001 độ, tôi đã lấp đầy một ổ cứng với các kết hợp lat lon gây ra một ngoại lệ, một ngoại lệ có thể lặp lại đáng tin cậy, trong suốt một tháng cũng kiểm tra độ tin cậy của việc làm mát CPU fan hâm mộ, và sự kiên nhẫn của tôi Có, tôi đã xóa hầu hết các bản ghi đó, vì mục đích của chúng chủ yếu là để chứng minh luận điểm (nếu cách chơi chữ được cho phép). Nhưng tôi có một số nhật ký ngắn hơn về 'giá trị lat lat', được giữ cho mục đích thử nghiệm.
Độ chính xác: Liệu một và toàn bộ kết quả haversine sẽ mất một số độ chính xác bằng cách bình thường hóa nó một chút trở lại miền? Không nhiều, có lẽ không nhiều hơn các phép tính gần đúng và làm tròn fp64 đã được giới thiệu, điều đó gây ra sự trôi dạt ra khỏi miền. Nếu bạn đã tìm thấy haversine chấp nhận được trên vincenty rồi - đơn giản hơn, nhanh hơn, dễ tùy chỉnh, khắc phục sự cố và bảo trì hơn, thì haversine có thể là một giải pháp tốt cho dự án của bạn.
Tôi đã sử dụng haversine trên một bầu trời được chiếu trên cao để đo khoảng cách góc giữa các vật thể trên bầu trời, khi nhìn từ một vị trí trên trái đất, ánh xạ góc phương vị và alt đến các tọa độ tương tự như skysphere lat lon, không xem xét elipsoid skysphere lý thuyết dự kiến là một hình cầu hoàn hảo, khi nói đến việc đo khoảng cách góc nhìn góc giữa hai vật thể từ một vị trí trên bề mặt trái đất. Nó phù hợp với nhu cầu của tôi một cách hoàn hảo. Vì vậy, haversine vẫn rất hữu ích và rất chính xác, trong một số ứng dụng (cũng nằm trong mục đích của tôi) ... nhưng nếu bạn sử dụng nó, cho dù trên trái đất cho GIS hay điều hướng, hoặc trong các quan sát và đo lường đối tượng trên bầu trời, hãy bảo vệ nó trong trường hợp các điểm đối cực hoặc rất gần các điểm đối cực, bằng cách thử nghiệm mộtvà đưa nó trở lại miền cần thiết của nó khi cần thiết.
Các haversine không được bảo vệ là tất cả trên internet và tôi chỉ thấy một bài đăng cũ sử dụng cho thấy sự bảo vệ, tôi nghĩ từ một người nào đó ở JPL, và đó có thể là trước năm 1985, thông số kỹ thuật điểm nổi trước 754 của IEEE. Hai trang khác đã đề cập đến các vấn đề có thể xảy ra gần các điểm đối cực, nhưng không mô tả các vấn đề đó, hoặc làm thế nào một người có thể giảm thiểu chúng. Vì vậy, có mối quan tâm đối với những người mới (như tôi), những người có thể không phải lúc nào cũng hiểu thực hành tốt đủ để nghiên cứu thêm và thử nghiệm các edgecase, về một số mã họ đã sao chép và dán vào một dự án đáng tin cậy. Bài đăng hấp dẫn của cffk đã được làm mới ở chỗ nó công khai với các loại vấn đề này, thường không được đề cập, hiếm khi được mã hóa công khai để bảo vệ trong đoạn trích, và hiếm khi được thảo luận theo cách này, so với số lượng phiên bản không được bảo vệ và không được phát hiện.
Kể từ năm 20190923, trang wiki về công thức haversine thực sự đã đề cập đến vấn đề có thể xảy ra tại các điểm đối cực, do các vấn đề về dấu phẩy động trong các thiết bị máy tính ... đáng khích lệ ...
https://en.wikipedia.org/wiki/Haversine_formula
(vì lúc này trang wiki không có neo html cho phần mà tôi sẽ liên kết trực tiếp, do đó, sau khi tải trang, hãy tìm kiếm trên trang trình duyệt đó để tìm 'Khi sử dụng các công thức này' và bạn sẽ xem vấn đề của haversine với các điểm đối cực được đề cập, chính thức hơn.)
Và trang web khác này cũng có một đề cập rất ngắn gọn về nó:
https://www.movable-type.co.uk/scripts/latlong.html
Nếu một người tìm thấy trên trang đó để 'bao gồm bảo vệ chống lại lỗi làm tròn', thì đây là ...
Nếu atan2 không có sẵn, c có thể được tính từ 2 ⋅ asin (min (1, √a)) (bao gồm cả bảo vệ chống lại lỗi làm tròn).
Bây giờ có một trường hợp hiếm hoi trong đó các lỗi làm tròn được đề cập và bảo vệ được hiển thị cho phiên bản asin (), nhưng chưa được đề cập hoặc hiển thị cho phiên bản atan2 (). Nhưng ít nhất là nguy cơ sai số làm tròn được đề cập.
imho, bất kỳ ứng dụng 24/7/365 nào sử dụng haversine, đều cần sự bảo vệ này gần các điểm đối cực như một chi tiết quan trọng và đơn giản.
Tôi không biết gói haversine nào hoặc không bao gồm bảo vệ này, nhưng nếu bạn chưa quen với tất cả những điều này và bạn sẽ sử dụng phiên bản 'đoạn trích' được xuất bản phổ biến, bây giờ bạn biết rằng nó cần được bảo vệ và bảo vệ đó rất đơn giản để thực hiện, nghĩa là, nếu bạn không sử dụng vincenty và không sử dụng một haversine đóng gói mà không dễ dàng truy cập để sửa đổi mã của gói.
IOW, cho dù sử dụng vincenty hay haversine hay sloc, người ta phải nhận thức được bất kỳ vấn đề nào với mã, những điều cần chú ý và giảm thiểu, và cách mọi người đối phó với các vấn đề vincenty vs haversine vs sloc sẽ khác nhau khi mỗi người nhận ra vấn đề ẩn giấu / edgecase, có thể hoặc không được biết đến phổ biến.