
Заключение
В лабораторной работе изучены интерполяция и аппроксимация функций. Интерполяция, с помощью полинома Лагранжа, обеспечивает точные значения в узловых точках, но может давать большие отклонения вне их. Аппроксимация методом наименьших квадратов лучше отражает общую тенденцию функции и подходит для данных с погрешностями, особенно для предсказания значений вне узлов. Выбор метода зависит от задачи: интерполяция нужна для точности в конкретных точках, аппроксимация — для анализа общей тенденции.
Приложение а
(обязательное)
Код для задания 1
using System;
using System.Linq;
class LagrangeApproximation
{
private double[] xValues = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8 };
private double[] y1Values = { -5.947752121, -4.267378922, -3.099338148, -0.258908702, 2.262736748, 3.550669271, 9.951284915, 16.32168104, 20.48808119, 31.18690729, 29.92614139, 40.72776343, 44.88657217, 55.84592817, 63.88514297 };
private double[] y2Values;
private double[] y3Values;
public LagrangeApproximation()
{
y2Values = xValues.Select(x => Math.Sqrt(5.99*x)).ToArray();
y3Values = xValues.Select(x => Math.Cos(5.44 * x)).ToArray();
}
public double LagrangeInterpolate(double x, double[] yValues)
{
double result = 0.0;
if (x < xValues[0] || x > xValues[xValues.Length - 1])
{
int n = xValues.Length;
double x0 = xValues[n - 3], x1 = xValues[n - 2], x2 = xValues[n - 1];
double y0 = yValues[n - 3], y1 = yValues[n - 2], y2 = yValues[n - 1];
result = ((x - x1) * (x - x2) * y0) / ((x0 - x1) * (x0 - x2)) +
((x - x0) * (x - x2) * y1) / ((x1 - x0) * (x1 - x2)) +
((x - x0) * (x - x1) * y2) / ((x2 - x0) * (x2 - x1));
}
else
{
for (int i = 0; i < xValues.Length - 2; i++)
{
if (x >= xValues[i] && x <= xValues[i + 2])
{
double x0 = xValues[i], x1 = xValues[i + 1], x2 = xValues[i + 2];
double y0 = yValues[i], y1 = yValues[i + 1], y2 = yValues[i + 2];
result = ((x - x1) * (x - x2) * y0) / ((x0 - x1) * (x0 - x2)) +
((x - x0) * (x - x2) * y1) / ((x1 - x0) * (x1 - x2)) +
((x - x0) * (x - x1) * y2) / ((x2 - x0) * (x2 - x1));
break;
}
}
}
return result;
}
public double[] LeastSquares(double[] yValues)
{
int n = xValues.Length;
double sumX = xValues.Sum();
double sumX2 = xValues.Sum(x => x * x);
double sumX3 = xValues.Sum(x => x * x * x);
double sumX4 = xValues.Sum(x => x * x * x * x);
double sumY = yValues.Sum();
double sumXY = xValues.Zip(yValues, (x, y) => x * y).Sum();
double sumX2Y = xValues.Zip(yValues, (x, y) => x * x * y).Sum();
double[,] A = {
{ sumX4, sumX3, sumX2 },
{ sumX3, sumX2, sumX },
{ sumX2, sumX, n }
};
double[] B = { sumX2Y, sumXY, sumY };
return SolveLinearSystem(A, B);
}
private double[] SolveLinearSystem(double[,] A, double[] B)
{
int n = B.Length;
double[] result = new double[n];
double[,] matrix = new double[n, n + 1];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
matrix[i, j] = A[i, j];
}
matrix[i, n] = B[i];
}
for (int i = 0; i < n; i++)
{
double maxElement = matrix[i, i];
int maxRow = i;
for (int k = i + 1; k < n; k++)
{
if (Math.Abs(matrix[k, i]) > maxElement)
{
maxElement = matrix[k, i];
maxRow = k;
}
}
for (int k = i; k < n + 1; k++)
{
double tmp = matrix[maxRow, k];
matrix[maxRow, k] = matrix[i, k];
matrix[i, k] = tmp;
}
for (int k = i + 1; k < n; k++)
{
double factor = matrix[k, i] / matrix[i, i];
for (int j = i; j < n + 1; j++)
{
matrix[k, j] -= factor * matrix[i, j];
}
}
}
for (int i = n - 1; i >= 0; i--)
{
result[i] = matrix[i, n] / matrix[i, i];
for (int k = i - 1; k >= 0; k--)
{
matrix[k, n] -= matrix[k, i] * result[i];
}
}
return result;
}
public static void Main()
{
var interp = new LagrangeApproximation();
for (int idx = 1; idx <= 3; idx++)
{
double[] yValues = idx == 1 ? interp.y1Values : (idx == 2 ? interp.y2Values : interp.y3Values);
Console.WriteLine($"\nРассчитываем для функции y{idx}:");
Console.Write($"Введите значение x для интерполяции функции y{idx}: ");
double xInterp = double.Parse(Console.ReadLine());
double lagrangeValue = Math.Round(interp.LagrangeInterpolate(xInterp, yValues), 4);
Console.WriteLine($"Значение интерполяции Лагранжа для x = {xInterp} и функции y{idx} равно {lagrangeValue}");
double[] coefficients = interp.LeastSquares(yValues);
Console.WriteLine($"Аппроксимация f(x) для y{idx} = {coefficients[0]:F4}x^2 + {coefficients[1]:F4}x + {coefficients[2]:F4}");
Console.Write($"Введите значение x для аппроксимации функции y{idx}: ");
double xApprox = double.Parse(Console.ReadLine());
double fXApprox = Math.Round(coefficients[0] * xApprox * xApprox + coefficients[1] * xApprox + coefficients[2], 4);
Console.WriteLine($"Значение аппроксимирующей функции f({xApprox}) для y{idx} = {fXApprox}");
}
}
}
Томск 2024