/// <summary> /// Генерирует интерполяционный многочлен Ньютона по узлам интерполяции /// </summary> /// <param name="interpolationNodes">Список узлов интерполяции</param> /// <param name="interpolationPoint">Точка интерполяции</param> /// <param name="polynomDegree">Степень искомого многочлена</param> /// <returns>Значение многочлена Ньютона в точке интерполяции</returns> static double CalcNewtonPolynom( InterpolationNodes interpolationNodes, double interpolationPoint, int polynomDegree) { var dividedDifference = new double[polynomDegree + 1, polynomDegree + 1]; for (int i = 0; i <= polynomDegree; ++i) { dividedDifference[i, 0] = F(interpolationNodes[i]); } for (int j = 1; j <= polynomDegree; ++j) { for (int i = 0; i <= polynomDegree - j; ++i) { dividedDifference[i, j] = (dividedDifference[i + 1, j - 1] - dividedDifference[i, j - 1]) / (interpolationNodes[i + j] - interpolationNodes[i]); } } double result = 0; double factor = 1; for (int j = 0; j <= polynomDegree; ++j) { result += dividedDifference[0, j] * factor; factor *= interpolationPoint - interpolationNodes[j]; } return(result); }
/// <summary> /// Генерирует интерполяционный многочлен Лагранжа по узлам интерполяции /// </summary> /// <param name="interpolationNodes">Список узлов интерполяции</param> /// <param name="interpolationPoint">Точка интерполяции</param> /// <param name="polynomDegree">Степень искомого многочлена</param> /// <returns>Значение многочлена Лагранжа в точке интерполяции</returns> static double CalcLagrangePolynom( InterpolationNodes interpolationNodes, double interpolationPoint, int polynomDegree) { double result = 0; for (int i = 0; i <= polynomDegree; ++i) { double numerator = 1; double denominator = 1; for (int j = 0; j <= polynomDegree; ++j) { if (j != i) { numerator *= interpolationPoint - interpolationNodes[j]; denominator *= interpolationNodes[i] - interpolationNodes[j]; } } result += numerator / denominator * F(interpolationNodes[i]); } return(result); }
/// <summary> /// Генерирует интерполяционный многочлен Лагранжа по узлам интерполяции /// </summary> /// <param name="interpolationNodes">Список узлов интерполяции</param> /// <param name="interpolationPoint">Точка интерполяции</param> /// <param name="polynomDegree">Степень искомого многочлена</param> /// <returns>Значение многочлена Лагранжа в точке интерполяции</returns> static double CalcLagrangePolynom( InterpolationNodes interpolationNodes, int polynomDegree, double interpolationPoint) { SortInterpolationTable(interpolationNodes, interpolationPoint); double result = 0; for (int i = 0; i <= polynomDegree; ++i) { double currentSum = 1; for (int j = 0; j <= polynomDegree; ++j) { if (j != i) { currentSum *= (interpolationPoint - interpolationNodes[j].X) / (interpolationNodes[i].X - interpolationNodes[j].X); } } result += currentSum * interpolationNodes[i].Fx; } return(result); }
static void Main(string[] args) { Console.Write("Введите m (число значений в таблице - 1): "); var tableSize = int.Parse(Console.ReadLine()); Console.Write("Введите a (левая граница промежутка интерполирования): "); var leftBorder = double.Parse(Console.ReadLine()); Console.Write("Введите b (правая граница промежутка интерполирования): "); var rightBorder = double.Parse(Console.ReadLine()); var interpolationTable = GenerateInterpolationTable(F, tableSize, leftBorder, rightBorder); var reverseInterpolationTable = new InterpolationNodes(interpolationTable.Select( entry => new InterpolationNode { X = entry.Fx, Fx = entry.X })); Console.WriteLine("Таблица интерполирования (x, f(x))"); foreach (var entry in interpolationTable) { Console.WriteLine($"x = {entry.X}; f(x) = {entry.Fx}"); } Console.WriteLine(); while (true) { Console.Write("Введите F (f(x) = F): "); var reverseInterpolationPoint = double.Parse(Console.ReadLine()); Console.Write("Введите n (степень интерполяционного многочлена): "); var polynomDegree = int.Parse(Console.ReadLine()); Console.WriteLine("В предположении, что функция строго монтонна:"); var interpolationResult = CalcLagrangePolynom(reverseInterpolationTable, polynomDegree, reverseInterpolationPoint); Console.WriteLine($"x = {interpolationResult}; " + $"Модуль невязки: {Math.Abs(F(interpolationResult) - reverseInterpolationPoint)}"); Console.WriteLine(); Console.WriteLine("В общем случае (2й метод): "); Console.Write("Введите ε (погрешность вычисления корней многочлена): "); var computationError = double.Parse(Console.ReadLine()); Func <double, double> shiftedInterpolationPolynom = point => CalcLagrangePolynom(interpolationTable, polynomDegree, point) - reverseInterpolationPoint; var interpolationPolynomRoots = FindRoots(shiftedInterpolationPolynom, leftBorder, rightBorder, computationError); foreach (var entry in interpolationPolynomRoots) { Console.WriteLine($"x = {entry}; Модуль невязки: {Math.Abs(F(entry) - reverseInterpolationPoint)}"); } Console.WriteLine(); Console.Write("Введите 0, чтобы выйти из программы; иное чтобы повторить"); var shouldExit = Console.ReadLine(); if (shouldExit == "0") { break; } } }
/// <summary> /// Генерирует равноотстоящие узлы интерполяции /// </summary> /// <param name="tableEntriesCount">Количество узлов интерполяции для генерации</param> /// <returns>Список узлов интерполяции</returns> static InterpolationNodes GenerateinterpolationNodes(int tableEntriesCount) { double stepWidth = (_rightInterpolationRangeBorder - _leftInterpolationRangeBorder) / tableEntriesCount; var result = new InterpolationNodes(); for (int i = 0; i < tableEntriesCount; ++i) { var currentPoint = _leftInterpolationRangeBorder + i * stepWidth; result.Add(currentPoint); } result.Add(_rightInterpolationRangeBorder); return(result); }
/// <summary> /// Генерирует таблицу интерполяции заданного размера /// </summary> /// <param name="function">Функция, по которой генерируем таблицу</param> /// <param name="tableSize">Размер таблицы минус 1</param> /// <param name="leftBorder">Левая граница интерполирования</param> /// <param name="rightBorder">Правая граница интерполирования</param> /// <returns></returns> static InterpolationNodes GenerateInterpolationTable( Func <double, double> function, int tableSize, double leftBorder, double rightBorder) { var step = (rightBorder - leftBorder) / tableSize; var resultNodes = new InterpolationNodes(); for (double position = leftBorder; position < rightBorder; position += step) { resultNodes.Add(new InterpolationNode { X = position, Fx = function(position) }); } return(resultNodes); }
/// <summary> /// Приблиительно высчитывает первую производную данной таблично заданной функции /// </summary> /// <param name="uniformTable">Таблица интерполирования с равноудаленными узлами</param> /// <returns>Таблично заданную первую производную</returns> static InterpolationNodes CalcFirstDerivatives(InterpolationNodes uniformTable) { double step = uniformTable[1].X - uniformTable[0].X; var result = new InterpolationNodes(); result.Add(new InterpolationNode { X = uniformTable[0].X, Fx = uniformTable.Count > 2 ? (-3 * uniformTable[0].Fx + 4 * uniformTable[1].Fx - uniformTable[2].Fx) / (2 * step) : (uniformTable[1].Fx - uniformTable[0].Fx) / step }); for (int i = 1; i < uniformTable.Count - 1; ++i) { result.Add(new InterpolationNode { X = uniformTable[i].X, Fx = (uniformTable[i + 1].Fx - uniformTable[i - 1].Fx) / (2 * step) }); } result.Add(new InterpolationNode { X = uniformTable[^ 1].X,
/// <summary> /// Сортирует узлы интерполяции по расстоянию до точки интерполяции /// </summary> /// <param name="table">Список узлов интерполяции для сортировки</param> /// <param name="interpolationPoint">Точка интерполяции</param> static void SortInterpolationNodes(InterpolationNodes table, double interpolationPoint) { table.Sort((first, second) => Math.Abs(first - interpolationPoint) < Math.Abs(second - interpolationPoint) ? -1 : 1); }
/// <summary> /// Сортирует таблицу интерполирования по удаленности узлов от точки интерполирования /// </summary> /// <param name="interpolationTable">Таблица узлов интерполирования</param> /// <param name="interpolationPoint">Точк интерполирования</param> static void SortInterpolationTable(InterpolationNodes interpolationTable, double interpolationPoint) { interpolationTable.Sort((node1, node2) => (int)(Math.Abs(interpolationPoint - node1.X) - Math.Abs(interpolationPoint - node2.X))); }