使用Math.Net Numerics对大x值进行错误的线性插值

时间:2014-06-16 13:10:49

标签: c# linear-interpolation mathdotnet numerics

我正在尝试使用Math.NET Numerics来插入DateTime - Value系列。我开始使用线性插值,但是我得到了一些看起来非常不合适的结果。

运行此测试:

public class script{

public void check_numerics()
  {
    var ticks = DateTime.Now.Ticks;
    Console.WriteLine("Ticks: " + ticks);
    var xValues = new double[] { ticks, ticks + 1000, ticks + 2000, ticks + 3000, ticks + 4000, ticks + 5000 };
    var yValues = new double[] {0, 1, 2, 3, 4, 5};
    var spline = Interpolate.LinearBetweenPoints(xValues, yValues);
    var ticks2 = ticks;
    for (int i = 0; i < 10; i++)
    {
      ticks2 += 500;
      Console.WriteLine(spline.Interpolate(ticks2));
    }
  }
}

这给出了:

Ticks: 635385235576843379
0.5
1
1.5
2
2.42857142857143 // this should be 2.5
3
3.5
4
4.5
5

请注意2.4285是完全错误的。在不同的时间(不同的刻度值),不同的值将是“错误的”。在Math.NET中是否存在具有大x值的“错误”,或者我期望太多?

1 个答案:

答案 0 :(得分:6)

刚刚确认上述评论为Math.NET Numerics的维护者:

可以双精度表示的最接近此数量的数字之间的距离(epsilon)为128:

Precision.EpsilonOf(ticks); // 128

这意味着如果您从此号码中添加或减去128/2-1 = 63,则会得到完全相同的数字:

long ticks = DateTime.Now.Ticks // 635385606515570758
((long)(double)ticks)           // 635385606515570816
((long)(63+(double)ticks))      // 635385606515570816
((long)(-63+(double)ticks))     // 635385606515570816
((long)(65+(double)ticks))      // 635385606515570944
((long)(-65+(double)ticks))     // 635385606515570688

500的增量步长非常接近这128并且有效地四舍五入到128的倍数(例如512),因此会出现一些像这样的工件并不奇怪。

如果你把时间精度减少到毫秒,你可以按照詹姆斯的建议将得分除以10000,你得到的ε为0.0078125,即使步数为1而不是500,也能得到准确的结果。

Precision.EpsilonOf(ticks/10000); // 0.0078125