Стандартный способ нормализации угла до + / - π радианов в Java

есть ли библиотечная функция или известный быстрый эффективный способ в Java нормализовать угол до +/- π - например, при добавлении двух углов?

то, что у меня есть сейчас (на основе ответ) в основном ниже код...

private static final double TWO_PI = 2 * Math.PI;

double normalize(double theta) {
    double normalized = theta % TWO_PI;
    normalized = (normalized + TWO_PI) % TWO_PI;
    return normalized <= Math.PI ? normalized : normalized - TWO_PI;
}

...но это кажется немного сложным и производительным, я не в восторге от оператора по модулю. (Обратите внимание, что я не могу гарантировать theta не является относительно большим числом, поэтому я не думаю, что есть чистый решение сложения / вычитания без зацикливания. Я на самом деле не знаю, как ручной цикл, вероятно, будет сравниваться с %.)

есть ли хорошо протестированная оптимизированная библиотечная функция, которую я могу использовать, или лучший алгоритм, или это так хорошо, как он получает?

2 ответов


Apache commons имеет один:

http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/util/MathUtils.html#normalizeAngle(double, double)

нормализовать угол между-π и + π

a = MathUtils.normalizeAngle(a, 0.0);

и, глядя на исходный код, вы можете воспроизвести его с помощью этого (они используют свои собственные FastMath.floor но в случае, если вы хотите сделать это без внешнего библиотека):

theta - TWO_PI * Math.floor((theta + Math.PI) / TWO_PI)

источник здесь: https://github.com/apache/commons-math/blob/53ec46ba272e23c0c96ada42f26f4e70e96f3115/src/main/java/org/apache/commons/math4/util/MathUtils.java#L107


Примечание Для читателей из будущего: этот метод только что (июнь 2017) удалены из последнего общего-математика 4.X кодовая база. Если вы используете версию после этого, вы захотите использовать Коммонс-числа вместо этого (после его выпуска) - в настоящее время:

a = PlaneAngleRadians.normalizeBetweenMinusPiAndPi(a);

или

a = PlaneAngleRadians.normalize(a, 0.0);

есть только один 100% надежный способ:

public static double normalizeAngle(double angle) {
    return Math.atan2(Math.sin(angle), Math.cos(angle));
}   

все остальное люди пытаются быть слишком умными и не.