Hallo zusammen!
Für ein Berechnungsprogramm benötige ich eine Methode, welche mir den Wert einer Winkelangabe (in Grad) normalisiert, was heißt, dass der als Eingangsparameter übergebene Winkel positiv wie negativ und beliebig groß sein kann (von Sonderfällen wie Infinity, NaN, ... kann abgesehen werden) und der Ausgabewert einem Wert des Vollkreis-Winkels entspricht, also im Intervall [0.0, 360.0[.
Ich habe mir dazu bereits zahlreiche Gedanken gemacht und recherchiert, habe aber noch keine für mich zufriedenstellende Lösung gefunden (sofern es denn eine gibt), da die Methode in mehrfach verschachtelten Schleifen ablaufen muss und daher entsprechend performant sein sollte.
Zuerst hatte ich diese Methode entwickelt:
[CODE lang="java" title="Variante 1"]public static double normalizeAngle_1(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else while(angle < 0.0) {
angle += 360.0;
}
return angle;
}[/CODE]
Ja, dieses abenteuerlich anmutende else-while-Konstrukt funktioniert, braucht jedoch einiges an Rechenzeit, wenn die Beträge größer werden.
Danach habe ich einige Varianten entwickelt:
[CODE lang="java" title="Variante 2"]public static double normalizeAngle_2(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = (360.0 + (angle % 360.0)) % 360.0;
}
return angle;
}[/CODE]
[CODE lang="java" title="Variante 3"]public static double normalizeAngle_3(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = angle + Math.ceil(-angle / 360.0) * 360.0;
}
return angle;
}[/CODE]
[CODE lang="java" title="Variante 4"]public static double normalizeAngle_4(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = 360.0 + (angle % 360.0);
if(angle >= 360.0) {
angle -= 360.0;
}
}
return angle;
}[/CODE]
Im Moment gehe ich davon aus, dass die 4. Variante die performanteste ist, da sie die wenigsten Modulo-Operationen und Methodenaufrufe enthält, dafür eine Fallunterscheidung mehr im worst-case. Ich frage mich, ob es nicht noch eine bessere Lösung gibt oder vielleicht eine vorgefertigte aus den Java-Bibliotheken, die ich nicht entdeckt habe...
Neben der Korrektheit ist wie gesagt die Performance wichtig und auf die Sonderfälle für die Eingangsparameter (Infinity, NaN, ...) braucht keine Rücksicht genommen zu werden!
Hat irgendjemand von euch hier bessere Vorschläge?
THX
tueftli
Für ein Berechnungsprogramm benötige ich eine Methode, welche mir den Wert einer Winkelangabe (in Grad) normalisiert, was heißt, dass der als Eingangsparameter übergebene Winkel positiv wie negativ und beliebig groß sein kann (von Sonderfällen wie Infinity, NaN, ... kann abgesehen werden) und der Ausgabewert einem Wert des Vollkreis-Winkels entspricht, also im Intervall [0.0, 360.0[.
Ich habe mir dazu bereits zahlreiche Gedanken gemacht und recherchiert, habe aber noch keine für mich zufriedenstellende Lösung gefunden (sofern es denn eine gibt), da die Methode in mehrfach verschachtelten Schleifen ablaufen muss und daher entsprechend performant sein sollte.
Zuerst hatte ich diese Methode entwickelt:
[CODE lang="java" title="Variante 1"]public static double normalizeAngle_1(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else while(angle < 0.0) {
angle += 360.0;
}
return angle;
}[/CODE]
Ja, dieses abenteuerlich anmutende else-while-Konstrukt funktioniert, braucht jedoch einiges an Rechenzeit, wenn die Beträge größer werden.
Danach habe ich einige Varianten entwickelt:
[CODE lang="java" title="Variante 2"]public static double normalizeAngle_2(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = (360.0 + (angle % 360.0)) % 360.0;
}
return angle;
}[/CODE]
[CODE lang="java" title="Variante 3"]public static double normalizeAngle_3(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = angle + Math.ceil(-angle / 360.0) * 360.0;
}
return angle;
}[/CODE]
[CODE lang="java" title="Variante 4"]public static double normalizeAngle_4(double angle) {
if(angle >= 360.0) {
angle %= 360.0;
}
else if(angle < 0.0) {
angle = 360.0 + (angle % 360.0);
if(angle >= 360.0) {
angle -= 360.0;
}
}
return angle;
}[/CODE]
Im Moment gehe ich davon aus, dass die 4. Variante die performanteste ist, da sie die wenigsten Modulo-Operationen und Methodenaufrufe enthält, dafür eine Fallunterscheidung mehr im worst-case. Ich frage mich, ob es nicht noch eine bessere Lösung gibt oder vielleicht eine vorgefertigte aus den Java-Bibliotheken, die ich nicht entdeckt habe...
Neben der Korrektheit ist wie gesagt die Performance wichtig und auf die Sonderfälle für die Eingangsparameter (Infinity, NaN, ...) braucht keine Rücksicht genommen zu werden!
Hat irgendjemand von euch hier bessere Vorschläge?
THX
tueftli