16

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不是某个相对较大的数字,所以我认为没有没有循环的纯加法/减法解决方案。我实际上不知道手动循环与%. )

是否有一个我可以使用的经过良好测试的优化库函数,或者更好的算法,或者它是否尽可能好?

4

2 回答 2

18

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 年 6 月)从最新的 commons-math 4.x 代码库中删除。如果您在此之后使用一个版本,您将希望使用commons-numbers代替(一旦它发布) - 目前:

a = PlaneAngleRadians.normalizeBetweenMinusPiAndPi(a);

或者

a = PlaneAngleRadians.normalize(a, 0.0);
于 2014-06-15T23:07:53.737 回答
14

只有一种 100% 万无一失的方法:

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

其他一切都是人们试图变得太聪明而失败。

于 2016-03-25T15:09:25.073 回答