不正确的线性插值与大的x值使用数学.净的数字
本文关键字:数字 插值 线性 不正确 | 更新日期: 2023-09-27 18:08:52
我想用数学。. NET数字来做一个日期时间值序列的插值。我开始与线性插值,但我得到一些非常不好看的结果。
运行此测试:
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是相当错误的。在不同的时间(不同的刻度值),不同的值将是"错误的"。是否有一个"bug"与大的x值在数学。NET还是我期望太高了?
只是确认上面的注释是Math的维护者。净的数字:
可以用双精度表示的这个星等最接近的数之间的距离(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),因此出现这样的一些伪影并不奇怪。
如果按照James的建议,通过将节拍除以10000,将时间精度降低到毫秒,则得到0.0078125的epsilon,并且即使是1步而不是500步也能得到准确的结果。
Precision.EpsilonOf(ticks/10000); // 0.0078125