มีข้อเสียของการใช้การตรวจสอบระยะทางมากกว่าการตรวจสอบระยะทาง?


29

ฉันใช้การตรวจสอบระยะทางกำลังสองสำหรับการตรวจสอบระยะทางทั้งหมด (ความยาวเวกเตอร์ 3) ของฉันเนื่องจากประสิทธิภาพที่เพิ่มขึ้นจากการไม่ทดสอบรากที่สอง (เช่นการตรวจสอบความยาวธรรมดา)

จากรูปลักษณ์ของมันการตรวจสอบระยะทางกำลังสองทำได้ดีในทุกสถานการณ์:

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

ฉันไม่ได้พิจารณาสถานการณ์ที่ x หรือ y น้อยกว่า 0 เนื่องจากระยะทางและระยะทางกำลังสองจะเป็นบวกเสมอ

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

คำตอบ:


41

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

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


16
รากที่สองจะลบความแม่นยำออกจากการตรวจสอบระยะทาง คุณสามารถนึกได้ว่ามันเป็นความพยายามที่จะหาสแควร์รูทของจำนวนจุดคงที่ระหว่าง 1 ถึง 2 และจัดเก็บผลลัพธ์ (ระหว่าง 1 ถึง sqrt (2)) ในช่วงเดียวกัน ระยะทางบางอย่างที่เปรียบเทียบเป็น x ^ 2 <y ^ 2 จะเปรียบเทียบเป็น x = y หลังจากคุณใช้สแควร์รูท การตรวจสอบความยาวกำลังสองนั้นเร็วขึ้นและแม่นยำยิ่งขึ้น
John Calsbeek

ขอบคุณสำหรับคำตอบที่ยอดเยี่ยมของคุณ bummzack และ John Calsbeek! คำตอบของคุณรวมกันอย่างสมบูรณ์ตอบคำถามของฉัน ฉันไม่ได้พิจารณาพื้นที่หน่วยความจำเพิ่มเติมจากการไม่ใช้สแควร์รูทซึ่งเป็นรถกระบะที่ดีจริงๆ และลิงค์ฮิวริสติกนั้นเหมาะสำหรับการอ่านที่ยอดเยี่ยม
Aralox

1
ยกเว้นในกรณีของ A * ฉันจำได้ว่ากำลังอ่านบทความที่อธิบายถึงการทดสอบฮิวริสติกที่แตกต่างกันและd^2ทำสิ่งที่น่ากลัว ใน A * |dx| + |dy|ทำงานได้ดี ฉันไม่มีลิงค์เมื่อฉันอ่านย้อนกลับไปหนึ่งเดือน
Jonathan Dickinson

3
ในกรณีของ A * คุณไม่เพียง แต่เปรียบเทียบระยะทาง แต่เพิ่มพวกเขาดังนั้นการข้าม sqrt จะสร้างความแตกต่าง
amitp

1
@bobobobo ฉันเห็นด้วย; ฉันส่วนใหญ่ทำให้มันเป็นการถกเถียงที่อาจเกิดขึ้นในอีกทางหนึ่งนั่นคือระยะทางปกตินั้นแม่นยำกว่า
John Calsbeek

14

ดังที่ bummzack บอกใบ้กับการเปรียบเทียบการค้นหาเส้นทางคุณจำเป็นต้องใช้ความยาว "ปกติ" ทุกครั้งที่คุณเพิ่มระยะทางด้วยกันและต้องการเปรียบเทียบผลรวมของพวกเขา (เพียงเพราะ summs ของกำลังสองของความยาวแตกต่างจาก summs ของความยาว)

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


4

ข้อเสียอย่างเดียวที่ฉันนึกได้คือเมื่อต้องรับมือกับคนจำนวนมากซึ่งจะล้นเมื่อกำลังสอง

ตัวอย่างเช่นใน 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!

นอกจากนี้ยังควรสังเกตว่าเป็นสิ่งที่เกิดขึ้นเมื่อคุณใช้Math.pow ()ด้วยตัวเลขที่แน่นอนและโยนกลับไปที่ int จาก double ที่ส่งคืนจาก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!

มันใช้ได้ไหม? ไม่มีก็เพียงให้คำตอบที่ถูกต้องเพราะy*yยึดติดอยู่Integer.MAX_VALUEและมีค่าน้อยกว่าx*x Integer.MAX_VALUEหากx*xถูกจับด้วยเช่นกันInteger.MAX_VALUEคุณจะได้รับคำตอบที่ไม่ถูกต้อง

หลักการที่คล้ายกันนี้ใช้กับการลอยตัวและการดับเบิล (ยกเว้นว่าพวกเขามีช่วงกว้างกว่าก่อนที่จะล้น) และภาษาอื่น ๆ ที่อนุญาตให้มีการไหลล้นอย่างเงียบ ๆ


คนส่วนใหญ่ใช้floatสำหรับพิกัดซึ่งล้นหลังจากนั้นประมาณไม่ได้10^38 int
bobobobo

แต่ที่ 10 ^ 38 คุณสูญเสียความแม่นยำอย่างมากจนคุณไม่สามารถแน่ใจได้ว่าการเปรียบเทียบระยะทางของคุณนั้นถูกต้องอีกต่อไป - ปัญหาน้ำท่วมไม่ใช่ปัญหาเดียวที่นี่ ดูaltdevblogaday.com/2012/02/05/dont-store-that-in-a-float (ส่วน "ตาราง" สรุปการสูญเสียความแม่นยำสูงถึง 1 พันล้าน)
Maximus Minimus

คุณจะมีปัญหาล้นเหมือนกันกับ sqrt (x * x) ฉันไม่เห็นประเด็นของคุณ นี่ไม่เกี่ยวกับระยะทางแมนฮัตตัน ฯลฯ
เกรงกลัว

@bogglez - ขึ้นอยู่กับว่าไลบรารี่ของคุณ (หรือ CPU) เพิ่มขึ้นเป็นสองเท่าหรือไม่
Maximus Minimus

3

มีอยู่ครั้งหนึ่งที่ฉันทำงานเป็นระยะทางสแควร์และทำผิดพลาดจากการสะสมระยะทางสแควร์สำหรับการนับระยะทาง

แน่นอนคุณไม่สามารถทำสิ่งนี้ได้เนื่องจากทางคณิตศาสตร์

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

ดังนั้นฉันจึงลงเอยด้วยผลลัพธ์ที่ไม่ถูกต้องที่นั่น อ๊ะ!


1
นอกจากนี้ฉันอาจเพิ่มว่ามีมากกว่าสองสามครั้งที่ฉันพยายามใช้ระยะทางกำลังสองเพียงเพื่อจะพบว่าฉันต้องการระยะทางจริงในภายหลังในรหัสสาขาเดียวกันนั้น ดังนั้นอย่าหักโหมจนเกินไป บางครั้งก็ไม่คุ้มค่าในความไม่สะดวกในการรักษาค่าสัมประสิทธิ์ Squared ทุกเมื่อคุณจำเป็นต้องสิ้นสุดการทำที่sqrtอยู่แล้วการดำเนินการ
bobobobo

3

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


ดูเหมือนว่าจะพิสูจน์ได้ซึ่งจะดีขึ้นหรือแย่ลงสำหรับสถานการณ์ที่กำหนด ฉันจำได้ว่านักคณิตศาสตร์มักเลือกที่จะใช้ระยะทางขยายเมื่อใส่เส้นตรงเข้ากับชุดของคะแนน บางทีพวกเขาอาจทำเช่นนั้นเพราะจะช่วยลดอิทธิพลของผู้ผิดกฎหมายคนเดียว ในกรณีที่สร้างสามของคุณค่าผิดปกติอาจไม่เป็นความเสี่ยง หรือบางทีพวกเขาทำมันเพราะจะง่ายต่อการทำงานร่วมกับกว่าx^2 |x|
joeytwiddle

@joeytwiddle Outliers มีผลกับการถดถอยเชิงเส้นมากขึ้นโดยมีกำลังสองน้อยที่สุดที่เหมาะกับระยะทางที่แน่นอน คุณพูดถูกเพราะใช้งานได้ง่ายกว่า ในตัวอย่างที่ฉันให้ (แม้ว่าจะมีการแก้ไขเพื่อให้มีอาคารจำนวนมาก) ระยะทางวัดกำลังสองจะถูกแก้ไขด้วยสูตรง่ายๆ (ค่าเฉลี่ยเลขคณิตของแต่ละพิกัด) แต่การวัดระยะทางสัมบูรณ์เป็นเรื่องยากทางคณิตศาสตร์และต้องเป็น แก้โดยประมาณโดยใช้หนึ่งในจำนวนของวิธีการเชิงตัวเลข
Alexander Gruber

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

0

การใช้ระยะทางกำลังสองนั้นเกือบจะดีและดีต่อประสิทธิภาพ ข้อควรพิจารณาต่อไปนี้มีความสำคัญ:

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

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

มันไม่สามารถยืนยันในกรณีที่ไม่ถูกต้องต่อไปนี้: a=36และb=49และในกรณีนี้ความยาวแรกคือ 6 และ 7 สอง ผลรวมของพวกเขามากกว่า 10 แต่ผลรวมของกำลังสองจะไม่เท่ากับ 100 หรือมากกว่า

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

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