0

So right now, I'm doing a homework assignment for a C++ class. The assignment says that I need to calculate the distance between two places using the haversine formula based on an input of degrees given by the user for longitude and latitude. Then the haversine formula calculates the distance between the two places.

The problem I'm having is when using the test values given by the instructor I get a greater answer than what he gets.

I'm calculating the distance between 33.9425/N 118.4081/W (LA Airport) and 20.8987/N 156.4305/W (Kahului Airport), where the LA Airport is the starting location.

His answer for the distance is 2483.3 miles. My answer is 2052.1 miles.

Here is my code for the haversine formula:

double haversine(double lat1, double lat2, double lon1, double lon2) {
    // get differences first
    double dlon = difference(lon1, lon2); // difference for longitude
    double dlat = difference(lat1, lat2); // difference for latitude
    // part a of algorithm
    double a = pow(sin(dlat/2), 2) + cos(lat1) * cos(lat2) * pow(sin(dlon/2), 2);
    // part b of algorithm
    double b = 2 * atan2(sqrt(a), sqrt(1 - a));
    // our result, or the great-circle distance between two locations
    double result = EARTH_RADIUS * b;
    return result;
}

And difference just returns y - x in this case. What seems to be going wrong in my calculations? As far as I know, my parentheses while calculating everything seem to be OK, so I'm not really sure why I'm getting a different answer.

Update: Fixed the problem by converting longitude and latitude in radians. In C++ I did this by defining PI = 3.14159265 and for each trig function I used, multiplying whatever was in there * PI/180. (ie. pow(sin((dlat/2) * (PI/180)),2)

Alex
  • 2,145
  • 6
  • 36
  • 72

2 Answers2

2

You need to convert your lats/longs to radians, because the trig functions in Java accept radian arguments.

public static double haversine(double lat1, double lon1, double lat2, double lon2) {
    double dLat = Math.toRadians(lat2 - lat1);
    double dLon = Math.toRadians(lon2 - lon1);
    lat1 = Math.toRadians(lat1);
    lat2 = Math.toRadians(lat2);

And this line:

// part b of algorithm
double b = 2 * atan2(sqrt(a), sqrt(1 - a));

is the same thing as

// part b of algorithm
double b = 2 * Math.asin(Math.sqrt(a));

Now your function should work. (:

Also, just for future reference:

// our result, or the great-circle distance between two locations
double result = EARTH_RADIUS * b;
return result;

Should be shortened to:

// our result, or the great-circle distance between two locations
return EARTH_RADIUS * b;

You should always be concise!

Tetramputechture
  • 2,911
  • 2
  • 33
  • 48
  • Would C++ have the same issue? Ie. just need to convert my latitudes and longitudes to radians? – Alex Oct 19 '14 at 05:55
0

This was something I wrote up using radians if you are allowed to not use the exact thing your teacher gave you. I had a project like this a while back and pulled the formula off different sites.

#include <iostream>

using namespace std;

static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
static const double EARTH_RADIUS_IN_MILES = 3959;

struct Position {
    Position(double lat, double lon) : _lat(lat), _lon(lon) {}
    void lat(double lat) { _lat = lat; }
    double lat() const { return _lat; }
    void lon(double lon) { _lon = lon; }
    double lon() const { return _lon; }
private:
    double _lat;
    double _lon;
};

double haversine(const Position& from, const Position& to) {
    double lat_arc = (from.lat() - to.lat()) * DEG_TO_RAD;
    double lon_arc = (from.lon() - to.lon()) * DEG_TO_RAD;
    double lat_h = sin(lat_arc * 0.5);
    lat_h *= lat_h;
    double lon_h = sin(lon_arc * 0.5);
    lon_h *= lon_h;
    double tmp = cos(from.lat()*DEG_TO_RAD) * cos(to.lat()*DEG_TO_RAD);
    return 2.0 * asin(sqrt(lat_h + tmp*lon_h));
}

double distance_in_meters(const Position& from, const Position& to) {
    return EARTH_RADIUS_IN_METERS*haversine(from, to);
}

double distance_in_miles(const Position& from, const Position& to)
{
    return EARTH_RADIUS_IN_MILES*haversine(from, to);
}

int main()
{
    double meters   = distance_in_meters(Position(33.9425, 118.4081), Position(20.8987, 156.4305));
    double miles    = distance_in_miles(Position(33.9425, 118.4081), Position(20.8987, 156.4305));
    cout << "\nDistance in meters is: " << meters;
    cout << "\nDistance in miles is: " << miles;


    cout << endl;
    system("PAUSE");
    return 0;
}
Jason Ball
  • 163
  • 8