该函数输出错误的值

时间:2017-09-05 08:45:43

标签: c#

当我输入这些坐标时,输出错误。

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

然后在我输入一些坐标的函数中。 41.507483 -99.436554 38.504048 -98.315949。这些坐标应该等于大约347但相反,我得到输出7022,88,这是错误的,我不知道为什么。

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");
}
}

2 个答案:

答案 0 :(得分:3)

正如您已经通过其他答案显示您的算法是正确的 - 您对用户输入的解析是错误的!

以下是演示:http://rextester.com/IEEA93176

原因是,在,中运行rextester的文化被用作小数分隔符 - 我认为它在你的环境中是相同的。在期望double.parse("41.1234")的文化中使用,时,您获得的值411234而不是41.1234

一个解决办法就是强迫文化

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

现场演示(工作):http://rextester.com/KALRN89806

答案 1 :(得分:2)

您对Haversine formula的实施没有任何问题 - 它会生成正确的输出。

以下打印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);
        }
    }
}

因此,您必须在别处寻找您的错误。我怀疑你没有为方法提供正确的值 - 我建议你在调试器中单步执行代码以确定发生了什么。

顺便说一下,您是否有任何理由不使用.Net GeoCoordinate类来计算?例如:

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

这会打印347.628192006498