RasBM
RasBM

Reputation: 27

The function outputs the wrong value

When ever I input these coordinates I get a wrong output.

static double ReadCoordinateFromConsole(double lat1, double lon1, double 
lat2, double lon2)
{
    var R = 6371; // Radius of the earth in km
    var dLat = deg2rad(lat2 - lat1);
    var dLon = deg2rad(lon2 - lon1);
    var a =
      Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
      Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) *
      Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
    var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
    var d = R * c; // Distance in km
    return d;
}

static double deg2rad(double deg)
{
    return deg * (Math.PI / 180);
}

Then in my function where I input some coordinates. 41.507483 -99.436554 38.504048 -98.315949. These coordinates should equal about 347 but instead, I get the output 7022,88 which is wrong and I have no clue as to why.

static double ReadDoubleFromConsole(string msg) 
while (true)
{
    Console.Write(msg);
    string test = Console.ReadLine();
    string[] words = test.Split(' ');
    bool inputContainsNumber = Regex.IsMatch(words[0], @"^-*[0-9,\.]+$");
    bool inputContainsNumber2 = Regex.IsMatch(words[1], @"^-*[0-9,\.]+$");
    bool inputContainsNumber3 = Regex.IsMatch(words[2], @"^-*[0-9,\.]+$");
    bool inputContainsNumber4 = Regex.IsMatch(words[3], @"^-*[0-9,\.]+$");
    if(inputContainsNumber && inputContainsNumber2 && inputContainsNumber3 
    && inputContainsNumber4)
    {
        double test1 = double.Parse(words[0]);
        double test2 = double.Parse(words[1]);
        double test3 = double.Parse(words[2]);
        double test4 = double.Parse(words[3]);
        double test5 = ReadCoordinateFromConsole(test1, test2, test3, 
        test4);
        return test5;
    }
    Console.WriteLine("hmm, doesn't look correct - try again");
}
}

Upvotes: 1

Views: 106

Answers (2)

Jamiec
Jamiec

Reputation: 136174

As you've been shown by the other answer your algorithm is correct - your parsing of the user input is wrong!

Here's the demonstration: http://rextester.com/IEEA93176

And the reason is, that in the culture that rextester runs in the , is used as a decimal separator - and I assume its the same in your environment. When you use double.parse("41.1234") in a culture expecting a , you get the value 411234 not 41.1234.

One fix is to force the culture

System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");

Live demo(working): http://rextester.com/KALRN89806

Upvotes: 3

Matthew Watson
Matthew Watson

Reputation: 109792

There's nothing wrong with your implementation of the Haversine formula - it generates the correct output.

The following prints 347.328348039426:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(ReadCoordinateFromConsole(41.507483, -99.436554, 38.504048, -98.315949));
        }

        static double ReadCoordinateFromConsole(double lat1, double lon1, double
            lat2, double lon2)
        {
            var R = 6371; // Radius of the earth in km
            var dLat = deg2rad(lat2 - lat1);
            var dLon = deg2rad(lon2 - lon1);
            var a =
                Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) *
                Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            var d = R * c; // Distance in km
            return d;
        }

        static double deg2rad(double deg)
        {
            return deg * (Math.PI / 180);
        }
    }
}

Therefore you must look elsewhere for your error. I suspect you're not feeding the correct values to the method - I recommend that you single-step your code in the debugger to determine what's happening.

Incidentally, is there any reason that you're not using the .Net GeoCoordinate class to calculate this? For example:

using System;
using System.Device.Location;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            var a = new GeoCoordinate(41.507483, -99.436554);
            var b = new GeoCoordinate(38.504048, -98.315949);

            Console.WriteLine(a.GetDistanceTo(b)/1000.0);
        }
    }
}

This prints 347.628192006498.

Upvotes: 2

Related Questions