Có bất kỳ nhược điểm nào của việc sử dụng kiểm tra Khoảng cách bình phương hơn là Khoảng cách không?


29

Tôi sử dụng kiểm tra bình phương khoảng cách cho tất cả các kiểm tra khoảng cách (chiều dài vector3) của tôi, do hiệu suất tăng từ việc không phát sinh căn bậc hai (như trong kiểm tra độ dài đơn giản).

Từ vẻ bề ngoài của nó, kiểm tra khoảng cách bình phương hoạt động tốt trong mọi tình huống:

if x^2 < y^2, then x < y, even when 0 < (x or y) < 1

Tôi không xem xét các tình huống trong đó x hoặc y nhỏ hơn 0, vì khoảng cách và bình phương khoảng cách luôn luôn dương.

Vì nó hoạt động, có vẻ như không bao giờ cần kiểm tra khoảng cách, nhưng tôi có cảm giác khó chịu rằng tôi đang thiếu thứ gì đó. Điều này sẽ vẫn giữ trong các tình huống quan trọng chính xác?

Câu trả lời:


41

Không có bất lợi nào tôi biết khi sử dụng chiều dài bình phương để so sánh khoảng cách. Hãy suy nghĩ về nó như thế: Bạn chỉ bỏ qua sqrtcái không cung cấp cho bạn bất kỳ độ chính xác bổ sung nào. Nếu bạn không cần khoảng cách Euclide thực tế, thì bạn có thể thoát ra một cách an toàn sqrt.

Tất nhiên, chiều dài bình phương tỷ lệ khá khác so với khoảng cách Euclide và do đó là một ứng cử viên tồi cho những thứ như heuristic tìm đường .


16
Căn bậc hai thực sự loại bỏ độ chính xác từ kiểm tra khoảng cách. Bạn có thể coi đó là một nỗ lực lấy căn bậc hai của một số điểm cố định trong khoảng từ 1 đến 2 và lưu trữ kết quả (giữa 1 và sqrt (2)) trong cùng một phạm vi. Một số khoảng cách so sánh là x ^ 2 <y ^ 2 sẽ so sánh là x = y sau khi bạn lấy căn bậc hai. Kiểm tra độ dài bình phương vừa nhanh hơn và chính xác hơn.
John Calsbeek

Cảm ơn bạn đã trả lời tuyệt vời của bạn bummzack và John Calsbeek! Câu trả lời của bạn kết hợp hoàn hảo trả lời câu hỏi của tôi. Tôi đã không xem xét không gian bộ nhớ bổ sung từ việc không sử dụng một căn bậc hai, thực sự tốt đẹp ở đó. Và liên kết heuristic đó làm cho một bài đọc tuyệt vời
Aralox

1
Trừ trường hợp A *. Tôi nhớ lại việc đọc một bài báo mô tả các thử nghiệm của các heuristic khác nhau và d^2thực hiện khủng khiếp. Trong A * |dx| + |dy|hoạt động độc đáo. Tôi không có liên kết khi tôi đọc lại khoảng một tháng.
Jonathan Dickinson

3
Trong trường hợp của A *, bạn không chỉ đơn thuần so sánh khoảng cách, mà thêm chúng vào, do đó bỏ qua sqrt sẽ tạo ra sự khác biệt.
amitp

1
@bobobobo Tôi đồng ý; Tôi chủ yếu làm cho nó bắn hạ một đối số tiềm năng theo hướng khác, tức là khoảng cách bình thường bằng cách nào đó chính xác hơn.
John Calsbeek

14

Như bummzack gợi ý với sự tương tự tìm đường, bạn CẦN sử dụng độ dài "bình thường" mỗi khi bạn thêm khoảng cách với nhau và muốn so sánh tổng của chúng. (Chỉ vì tổng bình phương có độ dài khác với tổng bình phương có độ dài).

x ^ 2 + y ^ 2! = (x + y) ^ 2


4

Nhược điểm duy nhất tôi có thể nghĩ đến là khi xử lý số lượng lớn sẽ tràn khi bình phương.

Ví dụ: trong Java:

int x = Integer.MAX_VALUE / 1000000; //2147
int y = Integer.MAX_VALUE / 5000; //429496
System.out.println("x < y: " + (x < y)); //true
System.out.println("x*x: " + (x * x)); //4609609
System.out.println("y*y: " + (y * y)); //-216779712 - overflows!
System.out.println("x*x < y*y: " + (x * x < y * y)); //false - incorrect result due to overflow!

Cũng đáng chú ý đó là những gì xảy ra khi bạn sử dụng Math.pow () với cùng một số chính xác và được trả về int từ số kép được trả về từ Math.pow():

System.out.println("x^2: " + (int) (Math.pow(x, 2))); //4609609
System.out.println("y^2: " + (int) (Math.pow(y, 2))); //2147483647 - double to int conversion clamps to Integer.MAX_VALUE
System.out.println("x^2 < y^2: " + ((int) (Math.pow(x, 2)) < (int) (Math.pow(y, 2)))); //true - but for the wrong reason!

Nó có hoạt động không? Không , nó chỉ đưa ra câu trả lời chính xác vì y*yđược kẹp chặt Integer.MAX_VALUE, và x*xít hơn Integer.MAX_VALUE. Nếu x*xcũng bị kẹp vào Integer.MAX_VALUEthì bạn sẽ nhận được câu trả lời không chính xác.

Các nguyên tắc tương tự cũng được áp dụng với số float & double (trừ khi chúng rõ ràng có phạm vi lớn hơn trước khi chúng tràn) và bất kỳ ngôn ngữ nào khác âm thầm cho phép tràn.


Hầu hết mọi người sử dụng floats cho tọa độ, chỉ tràn sau khoảng 10^38không int.
bobobobo

Nhưng vào lúc 10 ^ 38, bạn đã mất rất nhiều độ chính xác đến nỗi bạn thực sự không thể chắc chắn rằng các so sánh khoảng cách của bạn có giá trị nữa hay không - vấn đề tràn không phải là vấn đề duy nhất ở đây. Xem altdevblogaday.com/2012/02/05/dont-store-that-in-a-float (phần "Bảng" tóm tắt tổn thất chính xác lên tới 1 tỷ đồng).
Maximus Minimus

Bạn sẽ có cùng một vấn đề tràn với sqrt (x * x). Tôi không thấy quan điểm của bạn. Đây không phải là khoảng cách Manhattan, v.v.
bogglez

@bogglez - tùy thuộc vào việc thư viện (hoặc CPU) của bạn tăng lên gấp đôi hay không.
Maximus Minimus

3

Một lần tôi đang làm việc trong khoảng cách vuông, và đã phạm sai lầm khi tích lũy khoảng cách bình phương, cho một số đo đường.

Tất nhiên, bạn không thể làm điều này, bởi vì về mặt toán học,

(a^2+b^2+c^2+d^2)!=(a+b+c+d)^2

Vì vậy, tôi đã kết thúc với một kết quả không chính xác ở đó. Rất tiếc!


1
Ngoài ra tôi có thể thêm rằng đã có hơn một vài lần tôi đã thử sử dụng khoảng cách bình phương, chỉ để thấy tôi cần khoảng cách thực tế sau đó trong cùng một nhánh mã. Vì vậy, đừng lạm dụng nó. Đôi khi nó không đáng để bất tiện trong việc giữ các hệ số bình phương ở mọi nơi, khi bạn vẫn cần phải thực hiện sqrtthao tác.
bobobobo

3

Bạn có thể gặp rắc rối nếu bạn đang viết một thuật toán yêu cầu bạn tính toán một vị trí được tối ưu hóa. Ví dụ: giả sử bạn có một bộ đối tượng và bạn đang cố tính toán vị trí với tổng khoảng cách nhỏ nhất từ ​​tất cả các đối tượng. Lấy một ví dụ cụ thể, giả sử chúng tôi đang cố gắng cung cấp năng lượng cho ba tòa nhà và chúng tôi muốn tìm ra nơi mà nhà máy điện sẽ đi để chúng tôi có thể kết nối nó với tất cả các tòa nhà bằng tổng chiều dài dây nhỏ nhất. Sử dụng chỉ số bình phương khoảng cách, bạn sẽ kết thúc với tọa độ x của nhà máy điện là trung bình của tọa độ x của tất cả các tòa nhà (và tương tự cho tọa độ y). Sử dụng thước đo khoảng cách thông thường, giải pháp sẽ khác và thường rất xa so với giải pháp bình phương khoảng cách.


Có vẻ như sẽ tốt hơn hoặc tốt hơn cho một tình huống nhất định. Tôi nhớ rằng các nhà toán học thường chọn sử dụng bình phương khoảng cách khi khớp một đường thẳng với một tập hợp các điểm. Có lẽ họ làm điều đó bởi vì nó làm giảm ảnh hưởng của các ngoại lệ đơn độc. Trong trường hợp ba tòa nhà của bạn, các ngoại lệ có thể không phải là một rủi ro. Hoặc có lẽ họ làm điều đó vì x^2dễ làm việc hơn |x|.
joeytwiddle

@joeytwiddle Outliers thực sự ảnh hưởng đến hồi quy tuyến tính nhiều hơn với các ô vuông nhỏ nhất phù hợp với khoảng cách tuyệt đối. Bạn nói đúng rằng nó được sử dụng vì nó dễ làm việc hơn. Trong ví dụ tôi đã đưa ra (ngay cả khi nó được sửa đổi để chứa một số lượng lớn các tòa nhà), số liệu bình phương khoảng cách được giải bằng một công thức đơn giản (trung bình số học của mỗi tọa độ), nhưng số liệu khoảng cách tuyệt đối có thể thu được về mặt toán học và phải đã giải quyết xấp xỉ bằng một trong một số phương pháp số.
Alexander Gruber

Cảm ơn vì sự đúng đắn của bạn. Tất nhiên bạn là đúng, vuông của khoảng cách tạo ra một lớn hơn lỗi cho giá trị ngoại biên, tăng ảnh hưởng của họ chứ không phải giảm nó, như tôi đã nói ở trên không đúng. Thật thú vị khi giải pháp khoảng cách tối thiểu tuyệt đối khó khăn hơn nhiều để tính toán.
joeytwiddle

0

Sử dụng bình phương khoảng cách hầu như luôn luôn tốt và tốt cho hiệu suất. Những cân nhắc sau đây rất quan trọng:

Nếu bạn muốn nghĩ về tổng của một số khoảng cách, bình phương khoảng cách sẽ không chính xác. Chẳng hạn, tôi có hai khoảng cách và tôi muốn đảm bảo tổng của chúng nhỏ hơn 10. Đoạn mã sau không chính xác:

a = get_distance_squared(c,d);
b = get_distance_squared(e,f);
assert(a+b < 10^2);

Nó không xác nhận trong trường hợp không hợp lệ sau: a=36b=49. Trong trường hợp này, độ dài đầu tiên là 6 và 7 thứ hai; tổng của chúng lớn hơn 10, nhưng tổng bình phương không phải là 100 hoặc lớn hơn.

Một cân nhắc khác: đối với khoảng cách có giá trị thực, bình phương khoảng cách sẽ luôn dương. Nếu bạn đang đo chuyển vị chẳng hạn, bạn có thể cần phải xử lý các giá trị âm và bình phương chúng sẽ không làm được.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.