Ich möchte Winkel vergleichen und eine Vorstellung von der Entfernung zwischen ihnen bekommen. Für diese Anwendung arbeite ich in Grad, aber es würde auch für Bogenmaß und Absolventen funktionieren. Das Problem bei Winkeln ist, dass sie von einer modularen Arithmetik abhängen, dh 0-360 Grad.
Angenommen, ein Winkel liegt bei 15 Grad und einer bei 45. Der Unterschied beträgt 30 Grad, und der 45-Grad-Winkel ist größer als der 15-Grad-Winkel.
Dies bricht jedoch zusammen, wenn Sie beispielsweise 345 Grad und 30 Grad haben. Obwohl sie richtig verglichen werden, beträgt der Unterschied zwischen ihnen 315 Grad anstatt der korrekten 45 Grad.
Wie kann ich das lösen? Ich könnte algorithmischen Code schreiben:
if(angle1 > angle2) delta_theta = 360 - angle2 - angle1;
else delta_theta = angle2 - angle1;
Aber ich würde eine Lösung vorziehen, die Vergleiche / Verzweigungen vermeidet und sich ausschließlich auf Arithmetik stützt.
quelle
Antworten:
Hier ist meine vereinfachte, verzweigungslose, vergleichsfreie, keine Min / Max-Version:
Das Modulo wurde entfernt, da die Eingaben ausreichend beschränkt sind (danke an Martin für den Hinweis).
Zwei abs, drei subtrahieren.
quelle
Was lässt Sie denken, dass 315 falsch ist? In einer Richtung sind es 315 Grad, in der anderen Richtung 45. Sie möchten den kleinsten der beiden möglichen Winkel auswählen, und dies scheint an sich eine Bedingung zu erfordern. Sie können es nicht mit Umlauf-Arithmetik lösen (dh mit dem Modul-Operator), da der Winkel zwischen ihnen mit zunehmendem Winkel immer größer wird, bis er 180 erreicht und dann abnimmt.
Ich denke, Sie müssen entweder beide Winkel prüfen und entscheiden, in welche Richtung Sie messen möchten, oder beide Richtungen berechnen und entscheiden, welches Ergebnis Sie erzielen möchten.
quelle
Es gibt immer den Trick, beide Verzweigungen auszuführen und das Vergleichsergebnis eine auswählen zu lassen:
Ich kenne keine Möglichkeit, ohne Vergleiche vorzugehen , aber normalerweise macht der Zweig den Code langsam und lang, nicht der Vergleich. Zumindest ist dies meiner Meinung nach lesbarer als Martins Antwort (jeder gute C-Programmierer erkennt es als verzweigungsloses Äquivalent und sieht, was es tut), aber auch weniger effizient.
Aber wie ich in meinem Kommentar sagte, sind branchless Algorithmen auf Prozessoren mit tiefen Pipelines und schlechter Vorhersage gut - ein Mikrocontroller hat normalerweise eine winzige Pipeline, und ein Desktop-PC hat normalerweise eine gute Vorhersage ist wahrscheinlich der beste Weg, wenn er die Befehlsanzahl verringert.
Wie immer gibt Ihnen die Profilerstellung, die für Ihr System so einfach wie das Zählen von Operationen sein kann, die richtige Antwort.
quelle
Angenommen, true ergibt -1 und false ergibt 0 und '~', '&' und '|' sind bitweise nicht , und und bzw. Operatoren, und wir arbeiten mit Zweierkomplementarithmetik:
quelle
Was ist damit?
Die Addition von 360 dient dazu, negative Unterschiede zu vermeiden, da ein Modulo einer negativen Zahl ein negatives Ergebnis liefert. Dann erhalten Sie das kleinere der beiden möglichen Ergebnisse.
Es gibt immer noch eine implizite Entscheidung, aber ich weiß nicht, wie ich sie vermeiden soll. Grundsätzlich vergleichen Sie die beiden Winkel, indem Sie den Unterschied im oder gegen den Uhrzeigersinn berechnen, und es scheint, dass Sie den kleineren dieser beiden Unterschiede ausdrücklich wünschen. Ich weiß nicht, wie ich dieses Ergebnis erzielen kann, ohne sie zu vergleichen. Das heißt, ohne "abs", "min", "max" oder einen ähnlichen Operator zu verwenden.
quelle
Obwohl Ihre Frage keinen Hinweis darauf enthielt, gehe ich davon aus, dass Ihre Winkelberechnungsfrage darauf zurückzuführen ist, dass Sie den Mindestwinkel zwischen zwei Vektoren kennen wollen .
Diese Berechnung ist einfach. Angenommen, A und B sind Ihre Vektoren:
angle_between = acos( Dot( A.normalized, B.normalized ) )
Wenn Sie nicht über Vektoren verfügen und diesen Ansatz verwenden möchten, können Sie anhand Ihrer Winkel Einheitslängenvektoren konstruieren
new Vector2( cos( angle ), sin ( angle ) )
.quelle
Grundsätzlich die gleiche Antwort wie bei JasonD, außer dass bitweise Operationen anstelle der Absolutwertfunktion verwendet werden.
Dies setzt voraus, dass Sie 16-Bit-Ganzzahlen haben!
quelle
Ich glaube
quelle
Da es Ihnen nur darum geht, Verzweigungen und "komplexe" Operationen zu eliminieren, die über das Rechnen hinausgehen, würde ich Folgendes empfehlen:
min(abs(angle1 - angle2), abs(angle2 - angle1))
Sie brauchen immer noch einen,
abs
obwohl alle Blickwinkel positiv sind. Andernfalls wird immer das negativste Ergebnis ausgewählt (und es wird immer genau eine negative Antwort für positives, eindeutiges a und b beim Vergleich von ab und ba geben).Hinweis: Dadurch wird die Richtung zwischen Winkel1 und Winkel2 nicht beibehalten. Manchmal braucht man das für KI-Zwecke.
Dies ähnelt der Antwort von CeeJay, eliminiert jedoch alle Module. Ich weiß nicht, wie hoch die Zykluskosten sind
abs
, aber ich vermute, dass es 1 oder 2 sind. Schwer zu sagen, wie hoch die Kostenmin
auch sind. Vielleicht 3? Zusammen mit einem Zyklus pro Subtraktion sollte diese Zeile also ungefähr 4 bis 9 kosten.quelle
Holen Sie sich den kleineren relativen Winkel in vorzeichenbehafteter (+/-) Form aus der Perspektive von haben in Richtung wollen :
Grad
Radiant
Begründung
Ich bin auf diesen Thread gestoßen, nachdem ich das herausgefunden hatte, auf der Suche nach einer Lösung, die Modulo vermeidet. Bisher habe ich keine gefunden . Diese Lösung dient zum Erhalten des perspektivischen Zeichens, da @ jacob-phillips diesen Kommentar gefragt hat . Es gibt billigere Lösungen, wenn Sie nur den kürzesten Winkel ohne Vorzeichen benötigen.
quelle
Es ist eine alte Frage, aber ich bin auf denselben Fall gestoßen - ich musste einen signierten Winkeldifferenz erhalten und am besten ohne Verzweigungen und schwere Mathematik. Dies ist, was ich am Ende mit:
Die Einschränkung ist, dass 'b' nicht mehr als 'N' Rotationen im Vergleich zu 'a' haben sollte. Wenn Sie dies nicht sicherstellen können und zusätzliche Operationen zulassen, verwenden Sie dies als erste Zeile:
Die Idee kam mir aus dem 13. Kommentar dieses Beitrags: http://blog.lexique-du-net.com/index.php?post/Calculate-the-real-difference-between-angles-keeping-the- Zeichen
quelle
Ich denke, ich könnte sagen
natürlich, wenn man bedenkt, dass der Winkel in Grad gemessen wird.
quelle