Java Math.toRadians(角度)与硬计算

Java Math.toRadians(角度)与硬计算,java,math,big-o,Java,Math,Big O,这个问题与另一个讨论有关 以下是投票结果最高的答案中的代码: /* * Calculate distance between two points in latitude and longitude taking * into account height difference. If you are not interested in height * difference pass 0.0. Uses Haversine method as its base. * * lat1,

这个问题与另一个讨论有关

以下是投票结果最高的答案中的代码:

/*
 * Calculate distance between two points in latitude and longitude taking
 * into account height difference. If you are not interested in height
 * difference pass 0.0. Uses Haversine method as its base.
 * 
 * lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
 * el2 End altitude in meters
 */
private double distance(double lat1, double lat2, double lon1, double lon2,
        double el1, double el2) {

    final int R = 6371; // Radius of the earth

    Double latDistance = deg2rad(lat2 - lat1);
    Double lonDistance = deg2rad(lon2 - lon1);
    Double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
            + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
            * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
    Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double distance = R * c * 1000; // convert to meters

    double height = el1 - el2;
    distance = Math.pow(distance, 2) + Math.pow(height, 2);
    return Math.sqrt(distance);
}

private double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}
得票最高的答案有以下评论:

“为什么不使用Math.toRadians()而不是deg2rad()?它会真正自我包容。”

我在中查找了Math.toRadians()方法,注意到:

“将以度为单位的角度转换为以弧度为单位的近似等效角度。从度到弧度的转换通常是不精确的。

  • 得票最多的答案的deg2rad方法是否比Math.toRadians()方法更精确
  • 使用deg2rad方法执行两个算术运算和一个Math.Pi查找,尚不清楚Math.toRadians()如何执行约定。假设此距离计算可能会频繁执行,并且需要快速响应用户输入,那么哪种转换方法可以更有效地进行缩放

  • 如果问题1的答案是这两种方法具有大致相同的不精确性/准确性,我想我会使用Math.toRadians。使用Math.ToRadians可以使代码更具可读性,我认为它也可以更有效地扩展

    Math.toRadians
    的实现方式如下:

    public static double toRadians(double angdeg) {
        return angdeg / 180.0 * PI;
    }
    
    1) 如果存在差异,则可以忽略不计<代码>数学。托拉迪安先除法,而这个答案先乘法


    2) 唯一确定答案的方法是测试它,但我认为两者都不快,因为它们都做相同的事情。

    在Java 9中,
    toRadians
    toDegrees
    的实现更改为:

    public static double toRadians(double angdeg) {
        return angdeg * DEGREES_TO_RADIANS;
    }
    
    public static double toDegrees(double angrad) {
        return angrad * RADIANS_TO_DEGREES;
    }
    
    其中,
    度到弧度
    弧度到度
    是文字常量。根据以下来源,这使JMH微基准测试的性能提高了3倍

    (我们还可以推断,JIT编译器没有执行与上述相同的优化。我认为这是因为这样的优化可能会改变计算结果。这通常会使其不正确。JIT编译器可能无法判断哪种方式会给出更准确的结果,而且肯定可以不判断准确度……还是再现性……是最重要的标准。)

    与此相关的JDK bug数据库条目包括:



    总之,Java 9和更高版本的答案是,标准的
    数学
    函数比替代版本快。(如果您要经常运行此计算,Java 8和更早版本中是否存在此问题仍然未经测试…

    (使用
    deg2rad()
    ),它可能值得将pi/180存储在一个常数中,因此您不必每次都重新计算它。这里的根本问题是double的精度有限,而且在任何语言中都不可能有这样精确的可逆转换。我相信
    Math.toRadians
    会精确到尽可能高的精度。但是确实不应该混淆
    Double
    Double
    之间的区别
    Double
    是一种基本类型,而
    Double
    是一种增加大量开销的包装类型。另外
    distance*distance
    Math.pow(distance,2)快
    此代码来源于原始帖子。在我的改编中,我将所有的双精度图像更改为双精度图像(以及更改为忽略高程变化)。我不知道为什么最初的作者将这两种功能混合在一起,因为它们没有使用任何包装类功能。我会接受Math.pow的建议,我确实忘记了这一部分!如果有一个更准确的转换,即
    Math.toRadians
    ,那么肯定有人会在过去20年或更长的时间内将此报告给Sun/Oracle所以…@StephenC有趣的是,你在2013年就提到了这一点。。。。