【问题标题】:Standard way to normalize an angle to +/- π radians in Java在 Java 中将角度标准化为 +/- π 弧度的标准方法
【发布时间】:2014-08-05 17:48:34
【问题描述】:

在 Java 中是否有库函数或众所周知的快速有效方法将角度标准化为 +/- π - 例如什么时候加两个角?

我现在得到的(基于this answer)基本上是下面的代码......

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

是否有我可以使用的经过良好测试的优化库函数,或者更好的算法,或者这是否已经达到了最好的水平?

【问题讨论】:

  • 您要四舍五入到最接近的 90 度(半 pi)或最接近的 180 度(全 pi)?
  • @Kon 180 度/全圆周率。
  • @StefanoSanfilippo 我已经阅读了该答案,但鉴于大多数 Java 数学/几何库都是以弧度为单位的,因此以弧度为单位的答案似乎比以度为单位的答案更好。
  • ...事实上@CupawnTae 提供了一个library function answer

标签: java radians


【解决方案1】:

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 月)been removed 来自最新的 commons-math 4.x 代码库。如果您在此之后使用某个版本,则需要改用 commons-numbers(一旦发布)- 目前:

a = PlaneAngleRadians.normalizeBetweenMinusPiAndPi(a);

a = PlaneAngleRadians.normalize(a, 0.0);

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 这种方法可能更准确(而且我认为提供了一个半封闭的范围,不像MathUtils),但它也慢了大约 40 倍(我的 15" MBP 上的中位数约为 190ns,与 ~ 4.9ns 使用MathUtils),这对于某些应用程序可能更重要。
    • 我同意,atan2 可能很慢。但它可以处理 NaN 和 ±Infinity 的情况。
    • MathUtils 也处理这些——它返回所有三个的 NaN,就像 atan2 一样。
    • 这种方法在某些角度会有奇怪的伪影。即使理论上可行,我也无法让它 100% 万无一失地工作。
    • 万无一失?可能吧,我不知道。但是通过使用 three 三角函数将算术值限制在算术范围内对我来说似乎有点过分了。几个 while() 语句同样安全(在边缘情况下加上一个 if())。
    猜你喜欢
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2011-04-14
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多