简体   繁体   中英

Java Math.toRadians(angle) vs hard-calculated

This question is related to another stackoverflow discussion distance between long&lat points

Here is the code from the top voted answer:

/*
 * 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);
}

The top voted answer has the following comment:

"Why not Math.toRadians() instead of deg2rad()? It would be really self-containing."

I looked up the Math.toRadians() method in the documentation and noticed this:

"Converts an angle measured in degrees to an approximately equivalent angle measured in radians. The conversion from degrees to radians is generally inexact. "

  1. Is the top voted answer's deg2rad method more or less exact than the Math.toRadians() method?
  2. Using the deg2rad method performs two arithmetic operations and one Math.Pi look up, its not clear how Math.toRadians() performs the convention. Assuming that this distance calculation may be performed frequently and quick response to user input is desired, which conversion method would scale more efficiently?

If the answer to question 1 is that the two methods have roughly the same inexactness/accuracy, I think that I would use Math.toRadians. Using Math.ToRadians makes the code more readable, and I assume that it would scale more efficiently as well.

Math.toRadians is implemented like this:

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

1) If there is a difference, it's negligible. Math.toRadians does the division first, while that answer does the multiplication first.

2) The only way to find out for sure is to test it, but I would expect that neither is faster since they both do the same thing.

In Java 9, the implementations of toRadians and toDegrees were changed to this:

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

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

where DEGREES_TO_RADIANS and RADIANS_TO_DEGREES are literal constants. According to the following sources, this gives a 3-fold performance increase in a JMH micro-benchmark.

(We can also infer that the JIT compiler is not performing an optimization that is equivalent to the above. I presume that is because such an optimization could alter the computation's results. That would make it incorrect in general . The JIT compiler probably cannot make the judgement which way gives more accurate results, and it certainly cannot judge if accuracy ... or reproducibility ... is the most important criterion.)

The JDK bug database entries that relate to this are:


In summary, the answer for Java 9 and later is that the standard Math functions are faster than the alternative version. (Whether this was true in Java 8 and earlier is still untested ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM