//Заполнение таблицы (вводим x - он считает y) private static void LoadTabl(FuncX func, out double yT, ref double[,] tabl, double a, bool writeResult) { Console.Write("Введите через пробел {0} значений x: ", tabl.GetLength(0)); string[] tmp = Console.ReadLine().Split(' '); yT = func(a); if (writeResult) { Console.WriteLine("Точное значение: {0:f6}", yT); Console.WriteLine("{0}\t{1}\t{2}", "i", "x", "y"); } for (int i = 0; i < tabl.GetLength(0); i++) { tabl [i, 0] = Convert.ToDouble(tmp [i]); tabl [i, 1] = Math.Pow(Math.Log(tabl [i, 0]), 2); if (writeResult) { Console.WriteLine("{0}\t{1:f0}\t{2:f6}", i, tabl [i, 0], tabl [i, 1]); } } if (writeResult) { Console.WriteLine("Таблица заполнена!\n"); } }
/* * Метод центральных прямоугольников * * @a - Начало интервала * @b - Конец интервала * @n - Количество шагов * @func - Наша функция * @eps - Точность * * Алгоритм: * 1) Строим таблицу для x_i и x_(i+1/2) * 2) Вычисляем I = h * summ_(i=0)^n (y_(i+1/2)) * 3) Проверяем достигли ли мы точности по Рунге-Кутта * а) вычисляем две таблицы с с шагом h и шагом 2h * б) вычисляем I для каждой * в) Выходим, если 1/3 * |I_2 - I_1| <= epsilon, иначе увеличиваем количество шагов * */ public static double rectangleMethodWithRunge(double a, double b, int n, FuncX func, double eps) { double[,] table1 = CreateTable(a, b, n, func); //Создаем таблицу с n шагов double step1 = (b - a) / n; n *= 2; double[,] table2 = CreateTable(a, b, n, func); //Создаем таблицу в 2n шагов double step2 = (b - a) / n; PrintTable(table1); PrintTable(table2); double o1 = 1 / 3; double result = rectangleMethod(table2, step2); //Вычисляем while (eps <= o1 * Math.Abs(result - rectangleMethod(table1, step1))) { table1 = table2; step1 = step2; n *= 2; table2 = CreateTable(a, b, n, func); step2 = (b - a) / n; result = rectangleMethod(table2, step2); } return(result); }
/* * Метод Гаусса * * @a - Начало интервала * @b - Конец интервала * @n - Количество шагов * @func - Наша функция * * Алгоритм: * 1) Строим таблицу для x_i и x_(i+1/2) * 2) Вычисляем I = h * summ_(i=0)^n (y_(i+1/2) * 3) Проверяем достигли ли мы точности по Рунге-Кутта * а) вычисляем две таблицы с с шагом h и шагом 2h * б) вычисляем I для каждой * в) Выходим, если 1/3 * |I_2 - I_1| <= epsilon, иначе увеличиваем количество шагов * */ public static double Gauss(double a, double b, int n, FuncX func) { double[,] table = { { 0, 2, 0, 0, 0, 0, 0, 0 }, { -0.5773502692, 1, 0.5773502692, 1, 0, 0, 0, 0 }, { -0.7745966692, 0.5555555556, 0, 0.8888888888, 0.7745966692, 0.5555555556, 0, 0 }, { -0.8611363115, 0.3478548451, -0.3399810436, 0.6521451549, 0.8611363115, 0.3478548451, 0.3399810436, 0.6521451549 } }; double result = 0.0; double tmp = (b - a) / 2; for (int i = 0; i < n; i++) { Console.WriteLine(table[n - 1, i * 2]); Console.WriteLine("{0} = {1} * f({2}) = {3}", i, table[n - 1, i * 2 + 1], (b + a) / 2 + tmp * table[n - 1, i * 2], table[n - 1, i * 2 + 1] * func((b + a) / 2 + tmp * table[n - 1, i * 2])); result += table[n - 1, i * 2 + 1] * func((b + a) / 2 + tmp * table[n - 1, i * 2]); } return(result * tmp); }
/// <summary> /// <para>2a</para> /// <para>Сделать меню с различными функциями и представить пользователю выбор, /// для какой функции и на каком отрезке находить минимум. </para> /// <para>Использовать массив (или список) делегатов, в котором хранятся различные функции</para> /// </summary> /// <param name="f">func for value calculation</param> /// <param name="min">out param for min value</param> /// <param name="a">start of a value</param> /// <param name="b">stop of a value</param> /// <param name="step">step of change a value</param> /// <param name="startInt">start index for search min value</param> /// <param name="stopInt">stop index for search min value</param> /// <returns>all values from file (see 'SaveResults' method)</returns> public static double[] SearchMin(FuncX f, out double min, double a, double b, double step = 0.5, int startInt = 0, int stopInt = 0) { String fn = "res.txt"; SaveResults(f, fn, a, b, step); return(Load(Min, fn, out min, FunkWithInterval, startInt, stopInt)); }
/* * Интерполяция - способ нахождения промежуточных значений некоторой величины * по имеющемуся набору отдельно известных данных. */ #region Метод Лагранжа /* * Строит интерполяционный многочлен Лагранжа уровней 0..level * Вычисляет точное, приближенное значения, а так же погрешности * абсолютную и относительную. * * @func - Наша функция * @level - Максимальная степень многочлена * @countNode - Число узлов * @a - точка, в которой нужно найти значение * @writeResult - Выводить ли все результаты в консоль * * #yT - игрик точное * #tabl - таблица значений функции при x_i * * Алгоритм: * 1) Заполняем таблицу значениями функции в заданных точках * 2) Вычисляем многочлен Лагранжа степеней 0..level * a) Находим индекс самого близкого значения к а * б) Записываем индексы элементов, которые будут учавствовать в вычислениях(наши x_i) * в) Вычисляем выражения вида y_i*l_i^(n), * где l_i^(n) = (... * (x-x_(i-1) * (x-x_(i+1) * ...)) / (... * (x_i-x_(i-1) * (x_i-x_(i+1) * ...)) * */ public static void LagrangeMethod(FuncX func, int level, int countNode, int a, bool writeResult) { double yT; double[,] tabl = new double[countNode, 2]; ; LoadTabl(func, out yT, ref tabl, a, writeResult); Solution(a, level, tabl, yT, writeResult); }
public static double rectangleMethodWithRunge(double a, double b, int n, FuncX func) { double[,] table1 = CreateTable(a, b, n, func); //Создаем таблицу с n шагов double step1 = (b - a) / n; PrintTable(table1); double result = rectangleMethod(table1, step1); return(result); }
public static void Main(string[] args) { FuncX <object, object> lambda = i => null; TestLog.Log("Lambda:"); WriteType(lambda); TestLog.Log("Method (object):"); WriteType((FuncX <object, object>)MethodObj); TestLog.Log("Method (object):"); WriteType((FuncX <int, object>)MethodInt); TestLog.Log("Method (object):"); WriteType((FuncX <string, object>)MethodString); }
/// <summary> /// <para>2</para> /// <para>Модифицировать программу нахождения минимума функции так, чтобы можно было передавать функцию в виде делегата.</para> /// </summary> /// <param name="f">func for value calculation</param> /// <param name="fileName">filename to write values</param> /// <param name="aStart">start of a value</param> /// <param name="aStop">stop of a value</param> /// <param name="step">step of change a value</param> public static void SaveResults(FuncX f, string fileName, double aStart, double aStop, double step) { using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { using (BinaryWriter bw = new BinaryWriter(fs)) { for (double a = aStart; a <= aStop; a += step) { bw.Write(f(a)); if ((aStop - aStart) % step != 0 && (a + step) > aStop) { bw.Write(f(aStop)); } } } } }
//Создание таблицы private static double[,] CreateTable(double a, double b, int n, FuncX func) { double[,] table = new double[4, n + 1]; double step = (b - a) / n; //Шаг //Заполняем с конца столбцы //Чтобы сразу заполнять X(i+1/2) и Y table [0, n] = b; table [1, n] = func(b); for (int i = n - 1; i >= 0; i--) { table [0, i] = table [0, i + 1] - step; //Xi table [1, i] = func(table [0, i]); //Yi table [2, i] = table [0, i] + (table [0, i + 1] - table [0, i]) / 2; //X(i+1/2) table [3, i] = func(table [2, i]); //Y(i+1/2) } return(table); }
/* * Составляет интерполяционный многочлен Ньютона * Для неравномерного шага. * Вычисляет точное, приближенное значения, а так же погрешности * абсолютную и относительную. * * @func - Наша функция * @countNode - Число узлов * @a - точка, в которой нужно найти значение * @interpolateForward - Интерополировать вперед? * @writeResult - Выводить ли все результаты в консоль * * #yT - игрик точное * #tabl - таблица значений функции при x_i * #matr - Таблица разделенных разностей * * Алгоритм: * 1) Заполняем таблицу значениями функции в заданных точках * 2) Заполняем матрицу разделенных разностей * 3) Интерполируем вперед или назад * а) * */ public static void NewtonMethod(FuncX func, int countNode, int a, bool interpolateForward, bool writeResult) { double yT; double[,] tabl = new double[countNode, 2]; double[,] matr = new double[countNode, countNode]; LoadTabl(func, out yT, ref tabl, a, writeResult); LoadRazdRaznost(tabl, ref matr); if (interpolateForward) { SolutionNutonVpered(tabl, matr, a, yT, writeResult); } else { SolutionNutonNazad(tabl, matr, a, yT, writeResult); } }