Я хотел бы записать класс LinearInterpolator, где X тип значения оси X и Y тип значения оси Y. Я не вижу, как сделать это таким образом, что X мог быть DateTime или двойное. Класс - что-то как ниже (который не тестируется):
class LinearInterpolator<X, Y>
{
private List<X> m_xAxis;
private List<Y> m_yAxis;
public LinearInterpolator(List<X> x, List<Y> y)
{
m_xAxis = x;
m_yAxis = y;
}
public Y interpolate(X x)
{
int i = m_xAxis.BinarySearch(x);
if (i >= 0)
{
return m_yAxis[i];
}
else
{
// Must interpolate.
int rightIdx = ~i;
if (rightIdx >= m_xAxis.Count)
--rightIdx;
int leftIdx = rightIdx - 1;
X xRight = m_xAxis[rightIdx];
X xLeft = m_xAxis[leftIdx];
Y yRight = m_yAxis[rightIdx];
Y yLeft = m_yAxis[leftIdx];
// This is the expression I'd like to write generically.
// I'd also like X to be compilable as a DateTime.
Y y = yLeft + ((x - xLeft) / (xRight - xLeft)) * (yRight - yLeft);
return y;
}
}
}
}
Это было бы легко в C++, но я плохо знаком с дженериками C#, таким образом, любая справка ценилась бы.
Используйте DateTime.Ticks
в качестве интерполированного значения. Вы можете использовать тип long
в качестве универсального для интерполяции между временами.
Нет хорошего способа делать математику из обобщенных шаблонов C #, поэтому вы должны сделать что-то вроде этого:
Y y = FromDouble<Y>(ToDouble(yLeft) + ((ToDouble(x) - ToDouble(xLeft)) /
(ToDouble(xRight) - ToDouble(xLeft))) *
(ToDouble(yRight) - ToDouble(yLeft)));
double ToDouble(object val)
{
if (val is DateTime)
return (double)((DateTime)val).Ticks;
else
return Convert.ToDouble(val);
}
T FromDouble<T>(double val)
{
if (typeof(T) == typeof(DateTime))
return (T)Convert.ChangeType(new DateTime((long)val), typeof(T));
else
return (T)Convert.ChangeType(val, typeof(T));
}
Я не тестировал код, поэтому считайте его псевдокодом.
Следует знать одно: C # не поддерживает переопределение оператора. Таким образом, такой код не работает.
Одно из решений, как сказал Споулсон, - это не использовать дженерики, а использовать int или long вместо T и использовать DateTime.Ticks.
Спасибо за совет. Я меняю свой подход и пишу интерполятор, который работает только для двойников; Я хочу, чтобы интерполяция была быстрой, поэтому предпочитаю не проверять типы во время выполнения.