/// <summary> /// Оценить погрешность интерполяционного полинома (Лагранжа) в точке при константе /// </summary> /// <param name="f">Интерполируемая функция</param> /// <param name="n">Стень полинома</param> /// <param name="a">Начало отрезка интерполирования</param> /// <param name="b">Конец отрезка интерполяции</param> /// <param name="x">Точка, в которой оценивается погрешность</param> /// <param name="Mn">Константа в погрешности</param> public static void LagEstimateErr(Func <double, double> f, int n, double a, double b, double x, double Mn = 0) { if (Mn <= 0) { double[] y = Point.PointsX(f, n, a, b); double q = Expendator.Min(y); double y1 = Math.Min(q, x); q = Expendator.Max(y); double y2 = Math.Max(q, x); //double e = y1 + (y2 - y1) / 2;//середина отрезка //Mn = Math.Abs(f(e)); Mn = FuncMethods.RealFuncMethods.NormC(f, y1, y2); } Polynom p = new Polynom(f, n, a, b); Console.WriteLine("Узлы интерполяции: "); Point.Show(Point.Points(f, n, a, b)); Console.WriteLine("Полученный полином: "); p.Show(); Console.WriteLine($"Значение полинома в точке {x} = {p.Value(x)}"); Console.WriteLine($"Значение функции в точке {x} = {f(x)}"); double t = Math.Abs(p.Value(x) - f(x)); Console.WriteLine($"Абсолютная величина погрешности в точке {x} = {t}"); Console.WriteLine($"Оценка погрешности при Mn = {Mn}: {t} <= {wn(f, n, a, b, x, Mn)}"); }
private void GiveDivisionByNOD() { int a = A.DimOfFractionalPath(), b = B.DimOfFractionalPath(), c = C.DimOfFractionalPath(); int max = Expendator.Max(a, b, c); for (int i = 0; i < max; i++) { A *= 10; B *= 10; C *= 10; } max = (int)Number.Rational.Nod((long)A, (long)B); A /= max; B /= max; C /= max; }
/// <summary> /// Объединение двух массивов с удалением одного из двух близких (ближе eps) друг к другу элементов /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="eps"></param> /// <returns></returns> public static double[] Distinct(double[] a, double[] b, double eps = 1e-6) { double[] m = Expendator.Union(a, b); Array.Sort(m); List <double> l = new List <double>(a.Length); l.Add(m[0]); int k = 0; for (int i = 1; i < m.Length; i++) { if (m[i] - m[k] >= eps) { l.Add(m[i]); k = i; } } return(l.ToArray()); }
/// <summary> /// Каррирование отображения в соответствии с параметрами /// </summary> /// <param name="C">Параметр каррирования</param> /// <param name="c">Фиксированные аргументы</param> /// <returns></returns> public CkToCnFunc CarrByFirstOrLastArgs(CarringType C = CarringType.LastArgs, params Complex[] c) { if (func == null) { CnToCFunction[] mas = new CnToCFunction[EDimention]; switch (C) { case CarringType.FirstArgs: for (int i = 0; i < mas.Length; i++) { mas[i] = (CVectors v) => this.FuncMas[i](new CVectors(Expendator.Union(c, v.ComplexMas))); } break; default: for (int i = 0; i < mas.Length; i++) { mas[i] = (CVectors v) => this.FuncMas[i](new CVectors(Expendator.Union(v.ComplexMas, c))); } break; } return(new CkToCnFunc(mas)); } else { VecToVec h; switch (C) { case CarringType.FirstArgs: h = (CVectors v) => func(new CVectors(Expendator.Union(c, v.ComplexMas))); break; default: h = (CVectors v) => func(new CVectors(Expendator.Union(v.ComplexMas, c))); break; } return(new CkToCnFunc(h)); } }
/// <summary> /// Интеграл от отображения по одному аргументу (другие зафиксированы) /// </summary> /// <param name="beforeArg">Фиксированные аргументы до изменяемого</param> /// <param name="afterArg">Фиксированные аргументы после изменяемого</param> /// <param name="t1"></param> /// <param name="t2"></param> /// <param name="t3"></param> /// <param name="t4"></param> /// <param name="tm"></param> /// <param name="tp"></param> /// <param name="eps"></param> /// <param name="pr"></param> /// <param name="gr"></param> /// <returns></returns> public CVectors IntegralAmoutOneArg(CVectors beforeArg, CVectors afterArg, double t1, double t2, double t3, double t4, double tm, double tp, double eps, double pr, double gr) { FuncMethods.DefInteg.GaussKronrod.ComplexVectorFunc tmp = (Complex x, int N) => this.Value(Expendator.Union(beforeArg.ComplexMas, new Complex[] { x }, afterArg.ComplexMas)).ComplexMas; return(new CVectors(FuncMethods.DefInteg.GaussKronrod.DINN5_GK(tmp, t1, t2, t3, t4, tm, tp, eps, pr, gr, this.EDimention))); }
/// <summary> /// Интерполяция кубическими сплайнами дефекта 1 по массиву точек /// </summary> /// <param name="P"></param> /// <param name="a">Граничное условие в начале отрезка</param> /// <param name="b">Граничное условие в конце отрезка</param> /// <param name="is0outcut">Должен ли сплайн равняться 0 вне отрезка задания</param> /// <returns></returns> public static Func <double, double> CubeSpline(Point[] P, double a = 0, double b = 0, bool is0outcut = false) { int n = P.Length - 1;//записать в новую переменную для облегчения double[] h = new double[n + 1]; double[] y = new double[n + 1]; hmax = P[1].x - P[0].x; for (int i = 1; i <= n; i++) { h[i] = P[i].x - P[i - 1].x;//Заполнение массива длин отрезков if (h[i] > hmax) { hmax = h[i]; } y[i] = P[i].y - P[i - 1].y; } //создание, заполнение и решение системы с трёхдиагональной матрицей SLAU S = new SLAU(n + 1); S.A[0, 0] = -4.0 / h[1]; S.A[0, 1] = -2.0 / h[1]; S.b[0] = -6.0 * y[1] / (h[1] * h[1]) + a; S.A[n, n - 1] = 2.0 / h[n]; S.A[n, n] = 4.0 / h[n]; S.b[n] = 6.0 * y[n] / (h[n] * h[n]) + b; for (int i = 1; i <= n - 1; i++) { S.A[i, i - 1] = 1.0 / h[i]; S.A[i, i] = 2 * (1.0 / h[i] + 1.0 / h[i + 1]); S.A[i, i + 1] = 1.0 / h[i + 1]; S.b[i] = 3 * (y[i] / h[i] / h[i] + y[i + 1] / h[i + 1] / h[i + 1]); } //S.b[0] = a; //S.b[n] = b; S.ProRace(); syst = S; //S.Show(); //создание и заполнение массива полиномов Polynom[] mas = new Polynom[n + 1]; Polynom.SplinePol = new string[n]; for (int i = 1; i <= n; i++) { Polynom p1, p2, p3, p4; p1 = (new Polynom(1, P[i].x, P[i].x)) * (2 * new Polynom(P[i - 1].x) + h[i]) / Math.Pow(h[i], 3) * P[i - 1].y; p2 = (new Polynom(1, P[i - 1].x, P[i - 1].x)) * (-2 * new Polynom(P[i].x) + h[i]) / Math.Pow(h[i], 3) * P[i].y; p3 = (new Polynom(1, P[i].x, P[i].x)) * (new Polynom(P[i - 1].x)) / Math.Pow(h[i], 2) * S.x[i - 1]; p4 = (new Polynom(1, P[i - 1].x, P[i - 1].x)) * (new Polynom(P[i].x)) / Math.Pow(h[i], 2) * S.x[i]; mas[i] = p1 + p2 + p3 + p4; SplinePol[i - 1] = String.Format("[{0};{1}]: {2}", P[i - 1].x, P[i].x, mas[i].ToString()); //mas[i].Show(); } //mas[0] = mas[1];mas[n + 1] = mas[n]; //создание производных сплайна Polynom[] mas1 = new Polynom[n + 1], mas2 = new Polynom[n + 1]; for (int i = 1; i <= n; i++) { mas1[i] = mas[i] | 1; mas2[i] = mas1[i] | 1; } DSpline = (double x) => { if (x <= P[1].x) { return(mas1[1].Value(x)); } if (x >= P[n].x) { return(mas1[n].Value(x)); } int i = 1; while (x > P[i].x) { i++; } return(mas1[i].Value(x)); }; D2Spline = (double x) => { if (x <= P[1].x) { return(mas2[1].Value(x)); } if (x >= P[n].x) { return(mas2[n].Value(x)); } int i = 1; while (x > P[i].x) { i++; } return(mas2[i].Value(x)); }; //создание общей функции и вывод return((double x) => { if (x <= P[1].x) { return (is0outcut) ? 0 : mas[1].Value(x); } if (x >= P[n].x) { return (is0outcut) ? 0 : mas[n].Value(x); } int i = 1; //while (x > P[i].x) i++; int i1 = 1, i2 = n; //реализация бинарного поиска while (i2 - i1 != 1) { int tmp = Expendator.Average(i1, i2); if (x > P[tmp].x) { i1 = tmp; } else { i2 = tmp; } } i = i2; return mas[i].Value(x); }); }