Reputation: 27
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
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
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