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

时间:2015-02-13 22:52:11

标签: java math big-o

此问题与另一个stackoverflow讨论distance between long&lat points

有关

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

/*
 * 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()?它真的会自包含。”

我在documentation中查找了Math.toRadians()方法并注意到了这一点:

“将以度为单位测量的角度转换为以弧度为单位测量的近似等效角度。从度数到弧度的转换通常不准确。

  1. 最高投票答案的deg2rad方法是否比Math.toRadians()方法更准确或更不准确?
  2. 使用deg2rad方法执行两个算术运算和一个Math.Pi查找,不清楚Math.toRadians()如何执行约定。假设可以频繁地执行这种距离计算并且需要快速响应用户输入,哪种转换方法可以更有效地扩展?
  3. 如果对问题1的回答是这两种方法具有大致相同的不精确性/准确性,我认为我会使用Math.toRadians。使用Math.ToRadians使代码更具可读性,并且我认为它也可以更有效地扩展。

2 个答案:

答案 0 :(得分:4)

Math.toRadians的实现方式如下:

public static double toRadians(double angdeg) {
    return angdeg / 180.0 * PI;
}

1)如果存在差异,则可以忽略不计。 Math.toRadians首先进行除法,而该答案首先进行乘法运算。

2)确定的唯一方法是测试它,但我希望它们都不会更快,因为它们都做同样的事情。

答案 1 :(得分:1)

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

public static double toRadians(double angdeg) {
    return angdeg * DEGREES_TO_RADIANS;
}

public static double toDegrees(double angrad) {
    return angrad * RADIANS_TO_DEGREES;
}

其中 DEGREES_TO_RADIANSRADIANS_TO_DEGREES 是文字常量。根据以下来源,这使 JMH 微基准测试的性能提高了 3 倍。

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

与此相关的 JDK 错误数据库条目是:


总而言之,Java 9 及更高版本的答案是标准 Math 函数比替代版本更快。 (这在 Java 8 及更早版本中是否正确还没有经过测试......)