Mesafe yerine Kare Kare çek kullanmanın herhangi bir dezavantajı var mı?


29

Temel olarak tüm mesafelerimde (vektör3 uzunluk) kontrol yapmak için kare kareli kontroller kullanıyorum, performansın karekök oluşturmamasından (düz uzunluk kontrollerinde olduğu gibi) dolayı.

Görünüşüne göre, kare mesafe kontrolleri her durumda iyi çalışır:

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

X veya y'nin 0'dan küçük olduğu durumları düşünmüyorum, çünkü mesafe ve mesafe kare her zaman pozitif olacaktır.

Bu işe yaradığından beri, uzaktan kontrollere hiç ihtiyaç duyulmuyor gibi gözüküyor, ama bir şeyi kaçırdığıma dair dırdırcı hissediyorum. Bu doğruluk açısından kritik durumlarda hala geçerli mi?

Yanıtlar:


41

Mesafeleri karşılaştırmak için kare uzunluğu kullanırken bildiğim bir dezavantaj yok. Bunun gibi düşünün: Siz sadece sqrtek bir doğruluk vermeyen şeyleri atlıyorsunuz . Gerçek Öklid mesafesine ihtiyacınız yoksa, güvenli bir şekilde sqrtdışarıda bırakabilirsiniz .

Elbette kare uzunluk Öklid mesafesinden oldukça farklı ölçeklenir ve bu nedenle yol bulma sezgiselliği gibi şeyler için kötü bir adaydır .


16
Karekök aslında mesafe kontrolünden doğruluğu kaldırır. Bunu, sabit nokta sayısının karekökünü 1 ile 2 arasında almak ve sonucu aynı aralıkta (1 ile sqrt (2) arasında) kaydetmek olarak düşünebilirsiniz. Karekök alındıktan sonra x ^ 2 <y ^ 2 ile karşılaştırılan bazı mesafeler x = y ile karşılaştırılır. Kare uzunluk kontrolü hem daha hızlı hem de daha doğrudur.
John Calsbeek

Mükemmel cevaplar bummzack ve John Calsbeek için teşekkür ederiz! Cevaplarınız birleştirilince soruma cevap veriyor. Ek bellek boşluğunun karekök kullanmamasını, orada gerçekten güzel bir seçim yapmayı düşünmedim. Ve bu
buluşma

1
A * hariç. Farklı sezgisel testlerden geçen ve d^2korkunç performans gösteren bir makale okudum . A * |dx| + |dy|güzel çalışıyor. Bir ay kadar önce okuduğum gibi bir bağlantım yok.
Jonathan Dickinson

3
A * durumunda, yalnızca mesafeleri karşılaştırmakla kalmaz, onları eklersiniz, bu nedenle sqrt atlamak bir fark yaratır.
sabah 19'12'de

1
@bobobobo Katılıyorum; Çoğunlukla diğer yöndeki potansiyel bir argümanı vurmayı başardım, yani normal mesafe bir şekilde daha kesindi.
John Calsbeek

14

Bummzack, Yol Bulma benzetmesine işaret ettiğinden, mesafeleri her eklediğinizde ve toplamlarını karşılaştırmak istediğinizde "normal" uzunluğu kullanmanız gerekir. (Sadece uzunlukların karelerinin toplamları, uzunlukların karelerinin toplamlarından farklı olduğu için).

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


4

Aklıma gelen tek dezavantaj, kare olduğunda taşacak büyük sayılarla uğraşmaktır.

Örneğin, Java’da:

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!

Ayrıca, Math.pow () yöntemini aynı numaralarla kullandığınızda ve int döndürdüğünüzde int tuşuna geri döndüğünüzde bunun ne olduğuna dikkat edilmesi gerekir 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!

Çalışıyormu? Hayır , sadece doğru cevabı verdi çünkü y*ykelepçeleniyor Integer.MAX_VALUEve x*xondan daha az Integer.MAX_VALUE. Eğer x*xayrıca sabitlemeyi Integer.MAX_VALUEo zaman yanlış bir cevap almak istiyorum.

Benzer prensipler aynı zamanda float'lar ve çiftler için de geçerlidir (taşmalarından önce açıkça daha geniş bir menzile sahip olmaları dışında) ve taşmalara sessizce izin veren diğer diller için de geçerlidir.


Çoğu insan kullanmak floatkoordinatları s, sadece taşma sonra yaklaşık 10^38değildir int.
bobobobo

Ancak 10 ^ 38'de çok fazla hassasiyet kaybettiniz, mesafe karşılaştırmalarınızın daha geçerli olduğundan emin olamayacaksınız - taşma buradaki tek sorun değil. Bkz. Altdevblogaday.com/2012/02/05/dont-store-that-in-a-float ("Tablolar" bölümü 1 milyara kadar hassas kaybı özetlemektedir).
Maximus Minimus

Sqrt (x * x) ile aynı taşma problemine sahip olacaksınız. Amacını anlamıyorum. Bu Manhattan uzaklığı vb.
İle

@bogglez - kütüphanenizin (ya da CPU'nuzun) ikiye katlanıp fırlamamasına bağlıdır.
Maximus Minimus

3

Bir keresinde kare mesafelerde çalışıyordum ve bir kilometre sayacı sayısı için kare mesafeler biriktirme hatası yaptım .

Tabii ki, bunu yapamazsınız çünkü matematiksel olarak

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

Bu yüzden orada yanlış bir sonuç ile sona erdi. Hata!


1
Ayrıca, kare mesafeleri kullanmayı denedim, ancak aynı kod dalında daha sonra gerçek mesafelere ihtiyacım olduğunu bulmak için birkaç defadan fazla olduğumu da ekleyebilirim . Yani, aşırıya kaçma. sqrtİşlemi tamamlamanız gerektiğinde bazen kare katsayıları her yerde tutmanın zorluğuna değmez .
bobobobo

3

Optimize edilmiş bir pozisyon hesaplamanızı gerektiren bir algoritma yazıyorsanız, başınız belaya girebilir. Örneğin, bir dizi nesneniz olduğunu ve konumu tüm nesnelerden en küçük toplam mesafeyle hesaplamaya çalıştığınızı varsayalım. Sadece somut bir örnek için, üç binaya enerji vermeye çalıştığımızı ve enerji santralinin nereye gideceğini bulmak istiyoruz, böylece en küçük toplam kablo uzunluğunu kullanarak onu tüm binalara bağlayabilelim. Mesafe karesi ölçüsünü kullanarak, santralin x koordinatını tüm binaların x koordinatlarının ortalaması olarak (ve y koordinatı için benzer şekilde) elde edersiniz. Sıradan mesafe metriğini kullanarak, çözüm farklı olacaktır ve çoğu zaman mesafe kare çözümünden çok uzakta olacaktır.


Belirli bir durum için hangisinin daha iyi ya da daha kötü olacağını tartışmalı görünüyor. Matematikçilerin çoğu zaman bir çizgiyi bir noktaya yerleştirirken mesafe-kare kullanmayı tercih ettiklerini hatırlıyorum. Belki de bunu yaparlar çünkü yalnız aykırıların etkisini azaltır. Üç bina durumunda, aykırı riskler olmayabilir. Belki de bunu yapıyorlar çünkü x^2çalışmaktan daha kolay |x|.
joeytwiddle

@joeytwiddle Outliers aslında lineer regresyonu mutlak mesafeden daha küçük karelere daha fazla etkiliyor. Kullanımı doğru, çünkü çalışmak daha kolay. Verdiğim örnekte (çok sayıda bina içerecek şekilde değiştirilmiş olsa bile), mesafe kare metriği basit bir formülle (her bir koordinatın aritmetik ortalaması) çözülür, ancak mutlak mesafe metriği matematiksel olarak birbirinin içine giremez ve olmalıdır. yaklaşık olarak birkaç sayısal yöntemden birini kullanarak çözüldü .
Alexander Gruber

Düzeltme için teşekkürler. Tabii ki haklısın, mesafenin karesi aykırı değerler için daha büyük bir hata oluşturuyor , yukarıda yanlış olarak belirttiğim gibi azaltma yerine etkilerini arttırıyor. Bu, en az mutlak mesafe çözümünün hesaplanmasının ne kadar zor olduğunu etkiliyor.
joeytwiddle

0

Mesafe karesini kullanmak neredeyse her zaman sadece iyidir ve performans için iyidir. Aşağıdaki hususlar önemlidir:

Birkaç mesafenin toplamını düşünmek isterseniz, mesafe kareleri yanlış olacaktır. Örneğin, iki mesafem var ve toplamlarının 10'dan az olduğundan emin olmak istiyorum. Aşağıdaki kod yanlış:

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

Aşağıdaki geçersiz durumda iddiada bulunamaz: a=36ve b=49. Bu durumda, ilk uzunluk 6 ve ikinci 7'dir; toplamları 10'dan büyük, ancak karelerin toplamı 100 veya daha büyük değil.

Bir başka husus: Gerçek değerli mesafeler için, mesafe karesi her zaman pozitif olacaktır. Örneğin yer değiştirmeyi ölçüyorsanız, negatif değerlerle uğraşmanız gerekebilir ve bunların karesi alınmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.