Apakah ada kelemahan menggunakan pemeriksaan Squared Distance daripada Distance?


29

Saya menggunakan cek kuadrat jarak untuk dasarnya semua jarak saya (panjang vector3) memeriksa, karena peningkatan kinerja dari tidak menimbulkan akar kuadrat (seperti dalam pemeriksaan panjang polos).

Dari tampilannya, pemeriksaan jarak kuadrat berfungsi dengan baik di setiap situasi:

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

Saya tidak mempertimbangkan situasi di mana x atau y kurang dari 0, karena jarak dan kuadrat-jarak selalu akan menjadi positif.

Karena ini berfungsi, sepertinya pemeriksaan jarak jauh tidak pernah dibutuhkan, tetapi saya merasa ada yang tidak beres. Apakah ini masih bertahan dalam situasi akurasi-kritis?

Jawaban:


41

Tidak ada kerugian yang saya ketahui ketika menggunakan panjang kuadrat untuk membandingkan jarak. Pikirkan seperti itu: Anda hanya melewatkan sqrtyang tidak memberi Anda akurasi tambahan. Jika Anda tidak membutuhkan jarak Euclidean yang sebenarnya, maka Anda dapat meninggalkannya dengan aman sqrt.

Tentu saja skala panjang kuadrat cukup berbeda dari jarak Euclidean dan karenanya merupakan kandidat yang buruk untuk hal-hal seperti heuristik pathfinding .


16
Root kuadrat sebenarnya menghilangkan akurasi dari pemeriksaan jarak. Anda dapat menganggapnya sebagai upaya untuk mengambil akar kuadrat dari angka titik tetap antara 1 dan 2 dan menyimpan hasilnya (antara 1 dan sqrt (2)) dalam kisaran yang persis sama. Beberapa jarak yang membandingkan x ^ 2 <y ^ 2 akan dibandingkan dengan x = y setelah Anda mengambil akar kuadrat. Pemeriksaan panjang kuadrat lebih cepat dan lebih akurat.
John Calsbeek

Terima kasih atas jawaban luar biasa Anda bummzack dan John Calsbeek! Tanggapan Anda dikombinasikan dengan sempurna menjawab pertanyaan saya. Saya tidak mempertimbangkan ruang memori tambahan karena tidak menggunakan akar kuadrat, pickup yang sangat bagus di sana. Dan tautan heuristik itu menjadi bacaan yang bagus
Aralox

1
Kecuali dalam kasus A *. Saya ingat pernah membaca sebuah artikel yang menggambarkan pengujian heuristik yang berbeda dan d^2berkinerja mengerikan. Dalam A * |dx| + |dy|berfungsi dengan baik. Saya tidak memiliki tautan saat saya membaca sekitar sebulan lalu.
Jonathan Dickinson

3
Dalam kasus A * Anda tidak hanya membandingkan jarak, tetapi menambahkannya, sehingga melewatkan sqrt tidak membuat perbedaan.
amitp

1
@obobobo Saya setuju; Saya sebagian besar berhasil menembak argumen potensial ke arah lain, yaitu jarak normal entah bagaimana menjadi lebih akurat.
John Calsbeek

14

Seperti bummzack mengisyaratkan dengan analogi Pencarian-jalan, Anda PERLU menggunakan panjang "normal" setiap kali Anda menambahkan jarak bersama dan ingin membandingkan jumlah mereka. (Hanya karena jumlah kuadrat panjang berbeda dengan jumlah kuadrat panjang).

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


4

Satu-satunya kelemahan yang bisa saya pikirkan adalah ketika berhadapan dengan angka besar yang akan meluap ketika kuadrat.

Misalnya, di Jawa:

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!

Juga patut dicatat bahwa itulah yang terjadi ketika Anda menggunakan Math.pow () dengan angka yang sama persis dan melemparkan kembali ke int dari ganda yang dikembalikan dari 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!

Apakah ini berhasil? Tidak , itu hanya memberikan jawaban yang benar karena y*ydijepit Integer.MAX_VALUE, dan x*xkurang dari Integer.MAX_VALUE. Jika x*xjuga dijepit Integer.MAX_VALUEmaka Anda akan mendapatkan jawaban yang salah.

Prinsip serupa juga berlaku dengan float & dobel (kecuali mereka jelas memiliki jangkauan lebih besar sebelum meluap) dan bahasa lain apa pun yang secara diam-diam memungkinkan luapan air.


Kebanyakan orang menggunakan floats untuk koordinat, yang hanya meluap setelah sekitar 10^38tidak int.
bobobobo

Tetapi pada 10 ^ 38 Anda telah kehilangan begitu presisi sehingga Anda benar-benar tidak dapat memastikan bahwa perbandingan jarak Anda valid lagi - melimpah bukan satu-satunya masalah di sini. Lihat altdevblogaday.com/2012/02/05/dont-store-that-in-a-float (bagian "Tabel" merangkum kehilangan presisi hingga 1 miliar).
Maximus Minimus

Anda akan memiliki masalah luapan yang sama dengan sqrt (x * x). Saya tidak mengerti maksud Anda. Ini bukan tentang jarak Manhattan dll.
bogglez

@bogglez - tergantung apakah pustaka Anda (atau CPU) meningkat untuk menggandakan atau tidak.
Maximus Minimus

3

Suatu kali saya bekerja dalam jarak kuadrat, dan melakukan kesalahan dengan mengumpulkan jarak kuadrat, untuk penghitungan odometer.

Tentu saja, Anda tidak dapat melakukan ini, karena secara matematis,

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

Jadi, saya berakhir dengan hasil yang salah di sana. Ups!


1
Saya juga dapat menambahkan bahwa ada lebih dari beberapa kali di mana saya mencoba menggunakan jarak kuadrat, hanya untuk menemukan saya membutuhkan jarak aktual kemudian dalam cabang kode yang sama. Jadi, jangan berlebihan. Terkadang tidak sebanding dengan ketidaknyamanan menjaga koefisien kuadrat di mana-mana, ketika Anda harus tetap melakukan sqrtoperasi.
bobobobo

3

Anda dapat mengalami masalah jika Anda menulis algoritma yang mengharuskan Anda menghitung posisi yang dioptimalkan. Sebagai contoh, katakanlah Anda memiliki satu set objek, dan Anda mencoba menghitung posisi dengan jarak total terkecil dari semua objek. Sebagai contoh konkret, katakanlah kita sedang mencoba memberi daya pada tiga bangunan, dan kami ingin mengetahui ke mana pembangkit listrik harus pergi sehingga kami dapat menghubungkannya ke semua bangunan menggunakan total panjang kawat terkecil. Dengan menggunakan metrik kuadrat jarak, Anda akan berakhir dengan koordinat x dari pembangkit listrik menjadi rata-rata koordinat x dari semua bangunan (dan analog dengan koordinat y). Menggunakan metrik jarak biasa, solusinya akan berbeda, dan seringkali sangat jauh dari solusi kuadrat jarak.


Tampaknya bisa diperdebatkan mana yang lebih baik atau lebih buruk untuk situasi tertentu. Saya ingat bahwa matematikawan sering memilih untuk menggunakan kuadrat-jarak ketika memasang garis ke sekumpulan poin. Mungkin mereka melakukan itu karena mengurangi pengaruh outlier sendirian. Dalam kasus tiga bangunan Anda, pencilan mungkin bukan risiko. Atau mungkin mereka melakukannya karena x^2lebih mudah untuk dikerjakan daripada |x|.
joeytwiddle

@ Joeytwiddle Outliers sebenarnya mempengaruhi regresi linier lebih banyak dengan kuadrat terkecil cocok daripada jarak absolut. Anda benar karena digunakan karena lebih mudah digunakan. Dalam contoh yang saya berikan (bahkan jika dimodifikasi mengandung sejumlah besar bangunan), metrik kuadrat jarak diselesaikan dengan rumus sederhana (rata-rata aritmatika dari masing-masing koordinat), tetapi metrik jarak absolut secara matematis tidak dapat dipecahkan dan harus dipecahkan kira-kira menggunakan salah satu dari sejumlah metode numerik.
Alexander Gruber

Terima kasih atas koreksinya. Tentu saja Anda benar, kuadrat jarak menghasilkan kesalahan yang lebih besar untuk outlier, meningkatkan pengaruhnya daripada menguranginya, seperti yang saya katakan salah di atas. Itu menarik betapa jauh lebih sulit solusi jarak paling tidak absolut untuk dihitung.
joeytwiddle

0

Menggunakan jarak kuadrat hampir selalu baik dan bagus untuk kinerja. Pertimbangan berikut ini penting:

Jika Anda ingin memikirkan jumlah dari sejumlah jarak, jarak kuadrat akan tidak akurat. Misalnya, saya memiliki dua jarak dan saya ingin memastikan jumlah mereka kurang dari 10. Kode berikut ini salah:

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

Gagal menegaskan dalam kasus tidak valid berikut: a=36dan b=49. Dalam hal ini, panjang pertama adalah 6 dan 7 kedua; jumlah mereka lebih besar dari 10, tetapi jumlah kotak tidak 100 atau lebih besar.

Pertimbangan lain: untuk jarak bernilai nyata, jarak kuadrat akan selalu positif. Jika Anda mengukur perpindahan misalnya, Anda mungkin harus berurusan dengan nilai negatif, dan mengkuadratkannya tidak akan berhasil.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.