Gibt es Nachteile bei der Verwendung von Distance-Squared-Checks anstelle von Distance?

29

Grundsätzlich verwende ich Distance-Squared-Checks für alle meine Distanzprüfungen (Vektor3-Länge), da die Leistung dadurch erhöht wird, dass keine Quadratwurzel entsteht (wie bei einfachen Längenprüfungen).

So wie es aussieht, funktionieren quadratische Distanzprüfungen in jeder Situation einwandfrei:

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

Ich berücksichtige keine Situationen, in denen x oder y kleiner als 0 ist, da die Entfernung und das Entfernungsquadrat immer positiv sein werden.

Da dies funktioniert, sieht es so aus, als wären nie Abstandskontrollen erforderlich, aber ich habe das quälende Gefühl, dass mir etwas fehlt. Wird dies in genauigkeitskritischen Situationen weiterhin Bestand haben?

Aralox
quelle

Antworten:

41

Es gibt keinen Nachteil, den ich kenne, wenn ich die quadratische Länge zum Vergleichen von Entfernungen verwende. Stellen Sie sich das so vor: Sie überspringen nur das, sqrtwas Ihnen keine zusätzliche Genauigkeit verleiht. Wenn Sie den tatsächlichen euklidischen Abstand nicht benötigen, können Sie diesen sicher weglassen sqrt.

Natürlich skaliert die quadratische Länge ganz anders als die euklidische Distanz und ist daher ein schlechter Kandidat für Dinge wie Pfadfindungsheuristiken .

Blödmann
quelle
16
Die Quadratwurzel entfernt tatsächlich die Genauigkeit aus der Entfernungsprüfung. Sie können sich das als einen Versuch vorstellen, die Quadratwurzel einer Festkommazahl zwischen 1 und 2 zu ziehen und das Ergebnis (zwischen 1 und sqrt (2)) in genau demselben Bereich zu speichern. Einige Entfernungen, die mit x ^ 2 <y ^ 2 verglichen werden, werden mit x = y verglichen, nachdem Sie die Quadratwurzel gezogen haben. Die Überprüfung der quadratischen Länge ist schneller und genauer.
John Calsbeek
Vielen Dank für Ihre hervorragenden Antworten, Bummzack und John Calsbeek! Ihre kombinierten Antworten beantworten meine Frage perfekt. Ich habe den zusätzlichen Speicherplatz nicht in Betracht gezogen, weil ich keine Quadratwurzel verwendet habe. Und dieser Heuristik-Link sorgt für eine gute Lektüre
Aralox
1
Außer im Fall von A *. Ich erinnere mich, einen Artikel gelesen zu haben, in dem das Testen verschiedener Heuristiken und d^2die schreckliche Leistung beschrieben wurden. In A * |dx| + |dy|klappt das ganz gut. Ich habe den Link nicht, als ich ungefähr einen Monat zuvor gelesen habe.
Jonathan Dickinson
3
Im Fall von A * werden Entfernungen nicht nur verglichen, sondern hinzugefügt. Das Überspringen des sqrt macht also einen Unterschied.
amitp
1
@ Bobobobo Ich stimme zu; Ich habe es meistens geschafft, ein mögliches Argument in die andere Richtung abzuschießen, dh die normale Distanz ist irgendwie genauer.
John Calsbeek
14

Wie Bummzack in der Analogie zur Pfadfindung angedeutet hat, MÜSSEN Sie jedes Mal die "normale" Länge verwenden, wenn Sie Entfernungen addieren und ihre Summe vergleichen möchten. (Nur weil die Summe der Längenquadrate sich von der Summe der Längenquadrate unterscheidet).

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

Imi
quelle
4

Der einzige Nachteil, den ich mir vorstellen kann, ist der Umgang mit großen Zahlen, die beim Quadrieren überlaufen.

Zum Beispiel in 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!

Beachten Sie auch, dass dies passiert, wenn Sie Math.pow () mit genau den gleichen Zahlen verwenden und von dem Double, das von zurückgegeben wird, auf int zurücksetzenMath.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!

Funktioniert es? Nein , es hat nur die richtige Antwort gegeben, weil y*yes festgeklemmt Integer.MAX_VALUEist und x*xkleiner als Integer.MAX_VALUE. Wenn x*xauch geklemmt Integer.MAX_VALUEwäre dann bekäme man eine falsche Antwort.

Ähnliche Prinzipien gelten auch für Floats & Doubles (außer sie haben offensichtlich eine größere Reichweite, bevor sie überlaufen) und jede andere Sprache, die stillschweigend Überläufe zulässt.

Caspar
quelle
Die meisten Leute benutzen floats für Koordinaten, die erst nach etwa 10^38nicht überlaufen int.
Bobobobo
Aber bei 10 ^ 38 haben Sie so viel Präzision verloren, dass Sie nicht mehr sicher sein können, ob Ihre Entfernungsvergleiche gültig sind - Überlauf ist hier nicht das einzige Problem. Siehe altdevblogaday.com/2012/02/05/dont-store-that-in-a-float (der Abschnitt "Tabellen" fasst Präzisionsverluste von bis zu 1 Milliarde zusammen).
Maximus Minimus
Sie haben das gleiche Überlaufproblem mit sqrt (x * x). Ich verstehe deinen Standpunkt nicht. Hier geht es nicht um Manhattan Entfernung usw.
bogglez
@bogglez - hängt davon ab, ob Ihre Bibliothek (oder CPU) auf das Doppelte up-castet oder nicht.
Maximus Minimus
3

Einmal arbeitete ich in quadratischen Abständen und machte den Fehler , quadratische Abstände für eine Kilometerzahl zu addieren.

Natürlich können Sie dies nicht tun, weil mathematisch,

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

Also habe ich dort ein falsches Ergebnis erzielt. Hoppla!

Bobobobo
quelle
1
Ich könnte auch hinzufügen, dass ich mehr als ein paar Mal versucht habe, quadratische Abstände zu verwenden, nur um herauszufinden, dass ich tatsächliche Abstände später in demselben Codezweig benötigte. Also übertreib es nicht. Manchmal lohnt es sich nicht, die quadratischen Koeffizienten überall beizubehalten, wenn Sie die sqrtOperation trotzdem ausführen müssen.
Bobobobo
3

Sie könnten Probleme bekommen, wenn Sie einen Algorithmus schreiben, der die Berechnung einer optimierten Position erfordert. Angenommen, Sie hatten eine Reihe von Objekten und haben versucht, die Position mit der geringsten Gesamtentfernung von allen Objekten zu berechnen. Nehmen wir als konkretes Beispiel an, wir versuchen, drei Gebäude mit Strom zu versorgen, und möchten herausfinden, wo das Kraftwerk stehen soll, damit wir es mit der kleinsten Gesamtdrahtlänge an alle Gebäude anschließen können. Bei Verwendung der Distanz-Quadrat-Metrik ergibt sich, dass die x-Koordinate des Kraftwerks der Durchschnitt der x-Koordinaten aller Gebäude ist (und analog für die y-Koordinate). Bei Verwendung der gewöhnlichen Abstandsmetrik wäre die Lösung anders und oft sehr weit von der Lösung im Quadrat der Entfernung entfernt.

Alexander Gruber
quelle
Es scheint fraglich, welches für eine gegebene Situation besser oder schlechter sein würde. Ich erinnere mich, dass Mathematiker beim Anpassen einer Linie an eine Reihe von Punkten oft das Distanzquadrat verwenden. Vielleicht tun sie das, weil es den Einfluss einzelner Ausreißer verringert. In Ihrem Fall mit drei Gebäuden sind Ausreißer möglicherweise kein Risiko. Oder vielleicht machen sie es, weil x^2es einfacher ist, damit zu arbeiten als |x|.
Joeytwiddle
@joeytwiddle Ausreißer beeinflussen die lineare Regression tatsächlich mehr mit Anpassungen der kleinsten Quadrate als mit absoluter Entfernung. Sie haben Recht, dass es verwendet wird, weil es einfacher ist, damit zu arbeiten. In dem Beispiel, das ich gegeben habe (auch wenn es geändert wurde, um eine große Anzahl von Gebäuden zu enthalten), wird die Abstandsquadratmetrik mit einer einfachen Formel (dem arithmetischen Durchschnitt jeder Koordinate) gelöst, aber die absolute Abstandsmetrik ist mathematisch nicht zu handhaben und muss es sein ungefähr mit einer von mehreren numerischen Methoden gelöst .
Alexander Gruber
Danke für die Korrektur. Natürlich haben Sie recht, das Quadrat der Distanz erzeugt einen größeren Fehler für Ausreißer, der deren Einfluss verstärkt, anstatt ihn zu verringern, wie ich oben fälschlicherweise angegeben habe. Es ist faszinierend, wie viel schwieriger es ist, die Lösung mit der geringsten absoluten Entfernung zu berechnen.
Joeytwiddle
0

Die Verwendung von Distance Squared ist fast immer in Ordnung und gut für die Leistung. Die folgenden Überlegungen sind wichtig:

Wenn Sie über die Summe mehrerer Entfernungen nachdenken möchten, ist die quadrierte Entfernung ungenau. Zum Beispiel habe ich zwei Entfernungen und ich möchte sicherstellen, dass ihre Summe kleiner als 10 ist. Der folgende Code ist falsch:

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

Es kann in dem folgenden ungültigen Fall nicht behauptet werden: a=36und b=49. In diesem Fall ist die erste Länge 6 und die zweite 7; Ihre Summe ist größer als 10, aber die Summe der Quadrate ist nicht 100 oder größer.

Eine weitere Überlegung: Bei real bewerteten Entfernungen ist das Quadrat der Entfernung immer positiv. Wenn Sie beispielsweise die Verschiebung messen, müssen Sie möglicherweise mit negativen Werten umgehen, und das Quadrieren dieser Werte reicht nicht aus.

Eingeschränktes Sühnopfer
quelle