fork(2) download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Microsoft.Win32.SafeHandles;
  7.  
  8. namespace NumIntegration
  9. {
  10. public class Program
  11. {
  12. /*
  13.   * TODO:
  14.   ^* 1. Численное интегрирование методом Трапеций
  15.   ^* 2. Численное интегрирование методом Трапеций с поправкой Эйлера
  16.   ^* 3. Проверка порядка точности для методов
  17.   ^* 4. Вычисление интеграла с точностью Eps с помощью апостериорной оценки Рунге
  18.   * 5. Вычисление интеграла с точностью Eps и автоматическим подбором шага с помощью ариорной оценки Рунге
  19.   * (*) Графичесоке описание: Вывести график изменения шага интегрирования (только для п.5)
  20.   */
  21.  
  22. /// <summary>
  23. /// Функция, от которой нужно посчитать интеграл
  24. /// </summary>
  25. /// <param name="x">Точка</param>
  26. /// <returns>Значение в точке</returns>
  27. public static double Function(double x)
  28. {
  29. //return x*Math.Log((1+x)/(1-x));
  30. /*double numenator = Math.Sin(x);
  31.   double cos = Math.Cos(x);
  32.   double denumentor = (cos * cos + 1);
  33.   return numenator / denumentor;*/
  34. return x*x*x;
  35. }
  36.  
  37. /// <summary>
  38. /// Взятый интеграл
  39. /// </summary>
  40. /// <param name="x">Точка</param>
  41. /// <returns>Значение в точке</returns>
  42. public static double AccurateValue(double x)
  43. {
  44. //double t = -Math.Cos(x);
  45. //return Math.Atan(t);
  46. return x*x*x*x/4.0;
  47. }
  48.  
  49. /// <summary>
  50. /// Точное значение интеграла
  51. /// </summary>
  52. /// <param name="a">Начало отрезка</param>
  53. /// <param name="b">Конец отрезка</param>
  54. /// <returns>Значение точного интеграла</returns>
  55. public static double AccurateIntegral(double a, double b)
  56. {
  57. if (a > b) return (-1) * (AccurateValue(a) - AccurateValue(b));
  58. return AccurateValue(b) - AccurateValue(a);
  59. }
  60.  
  61. public delegate double IntegralMethod(int pointsCount, double a, double b);
  62.  
  63. /// <summary>
  64. /// Первая производная подинтегральной функции
  65. /// </summary>
  66. /// <param name="x">Точка</param>
  67. /// <returns>Значение в точке</returns>
  68. public static double Deriative(double x)
  69. {
  70. /*double cos = Math.Cos(x);
  71.   double sin = Math.Sin(x);
  72.   return (2 * cos * sin * sin + cos * (cos * cos + 1)) / ((cos * cos + 1) * (cos * cos + 1));*/
  73. return 3*x*x;
  74. }
  75.  
  76. /// <summary>
  77. /// Метод, который меняет местами две переменные
  78. /// </summary>
  79. /// <param name="a">Ссылка на первый параметр</param>
  80. /// <param name="b">Ссылка на второй параметр</param>
  81. public static void Swap(ref double a, ref double b)
  82. {
  83. double temp = a;
  84. a = b;
  85. b = temp;
  86. }
  87.  
  88. /// <summary>
  89. /// Метод Трапеций
  90. /// </summary>
  91. /// <param name="a">Начало отрезка</param>
  92. /// <param name="b">Конец отрезка</param>
  93. /// <param name="step">Шаг</param>
  94. /// <returns>Приближенное значение интеграла, посчитанное данным методом</returns>
  95. public static double MethodTrapeze(double a, double b, int pointsCounts)
  96. {
  97. double count = 0.0;
  98. int minus = 1;
  99. if (a > b)
  100. {
  101. Swap(ref a, ref b);
  102. minus = -1;
  103. }
  104. double step = (b - a) / pointsCounts;
  105. double point = a + step;
  106. while (pointsCounts - 1 > 0)
  107. {
  108. count += Function(point);
  109. point += step;
  110. pointsCounts--;
  111. }
  112.  
  113. count = (count + 0.5 * (Function(a) + Function(b))) * step;
  114.  
  115. return count * minus;
  116. }
  117.  
  118. /// <summary>
  119. /// Численное интегрирование
  120. /// </summary>
  121. /// <param name="pointsCount">Количетсво точек</param>
  122. /// <param name="a">Начало отрезка</param>
  123. /// <param name="b">Конец отрезка</param>
  124. /// <returns>Значение интеграла</returns>
  125. public static double IntegralTrap(int pointsCount, double a, double b)
  126. {
  127. return MethodTrapeze(a, b, pointsCount);
  128. }
  129.  
  130. /// <summary>
  131. /// Численное интегрирование методом трапеций с поправкой Эйлера
  132. /// </summary>
  133. /// <param name="pointsCount">Количетсво точек</param>
  134. /// <param name="a">Начало отрезка</param>
  135. /// <param name="b">Конец отрезка</param>
  136. /// <returns>Значение интеграла</returns>
  137. public static double IntegralEuler(int pointsCount, double a, double b)
  138. {
  139. double step;
  140. if (a > b)
  141. step = (a - b) / pointsCount;
  142. else
  143. step = (b - a) / pointsCount;
  144. return MethodTrapeze(a, b, pointsCount) - step * step / 12 * (Deriative(b) - Deriative(a));
  145. }
  146.  
  147. public static void IntegralMethodTrapeze()
  148. {
  149. //double begin = Math.PI / 2, end = Math.PI;
  150. double begin = 2, end = 4;
  151. double accurateIntegral = AccurateIntegral(begin, end);
  152. Console.WriteLine("Точное значение интеграла: {0}", accurateIntegral);
  153. Console.WriteLine("<<<Метод трапеции>>>");
  154. Console.WriteLine(" Разбиение\t|\tИнтеграл\t|\tАбс. ошибка\t\t|\tПорядок");
  155. for (int i = 10; i <= 320; i *= 2)
  156. {
  157. double integral = IntegralTrap(i / 2, begin, end);
  158. double integral2 = IntegralTrap(i, begin, end);
  159. double absoluteError = Math.Abs(accurateIntegral - integral);
  160. double absoluteError2 = Math.Abs(accurateIntegral - integral2);
  161.  
  162. if (i == 10)
  163. {
  164. Console.WriteLine("\t{0}\t|\t{1:#0.#############}\t|\t{2,10}\t|\t -------------", i, integral2,
  165. absoluteError);
  166. continue;
  167. }
  168.  
  169. Console.WriteLine("\t{0}\t|\t{1:#0.#############}\t|\t{2,10}\t|\t{3:#0.#############}", i, integral2,
  170. absoluteError, absoluteError / absoluteError2);
  171. }
  172. }
  173.  
  174. public static void IntegralMethodEuler()
  175. {
  176. //double begin = Math.PI / 2, end = Math.PI;
  177. double begin = 2, end = 4;
  178. double accurateIntegral = AccurateIntegral(begin, end);
  179. Console.WriteLine("\n\n");
  180. Console.WriteLine("Точное значение интеграла: {0}", accurateIntegral);
  181. Console.WriteLine("<<<Метод трапеции с поправкой Эйлера>>>");
  182. Console.WriteLine(" Разбиение\t|\tИнтеграл\t|\tАбс. ошибка\t\t|\tПорядок");
  183.  
  184. for (int i = 10; i <= 320; i *= 2)
  185. {
  186. double integral = IntegralEuler(i / 2, begin, end);
  187. double integral2 = IntegralEuler(i, begin, end);
  188. double absoluteError = Math.Abs(accurateIntegral - integral);
  189. double absoluteError2 = Math.Abs(accurateIntegral - integral2);
  190.  
  191. if (i == 10)
  192. {
  193. Console.WriteLine("\t{0}\t|\t{1:#0.#############}\t|\t{2,10}\t|\t -------------", i, integral2,
  194. absoluteError);
  195. continue;
  196. }
  197.  
  198. Console.WriteLine("\t{0}\t|\t{1:#0.#############}\t|\t{2,10}\t|\t{3:#0.#############}", i, integral2,
  199. absoluteError, absoluteError / absoluteError2);
  200. }
  201. }
  202.  
  203. public static void Runge(int pointsCount, double begin, double end, IntegralMethod Integral, int p, double eps)
  204. {
  205. double integ;
  206. double integr;
  207. do
  208. {
  209. integ = Integral(pointsCount, begin, end);
  210. integr = Integral(2 * pointsCount, begin, end);
  211. pointsCount *= 2;
  212. } while (Math.Abs(integ - integr) >= (Math.Pow(2, p) - 1) * eps);
  213.  
  214. Console.WriteLine("Количество точек: " + pointsCount + "\nЗначение интеграла: " + integr);
  215. }
  216.  
  217. static void Main(string[] args)
  218. {
  219. IntegralMethodTrapeze();
  220.  
  221. IntegralMethodEuler();
  222.  
  223. double begin = Math.PI / 2, end = Math.PI;
  224. int pointsCount = 10;
  225. double eps = 2.5E-04;
  226. int p = 2;
  227. Console.WriteLine("Оценка Рунге для метода трапеций с eps = " + eps);
  228. Runge(pointsCount, begin, end, new IntegralMethod(IntegralTrap), p, eps);
  229.  
  230. p = 4;
  231. eps = 0.0000000001;
  232. Console.WriteLine("\nОценка Рунге для метода трапеций с eps = " + eps);
  233. Runge(pointsCount, begin, end, new IntegralMethod(IntegralEuler), p, eps);
  234.  
  235. Console.ReadKey();
  236. }
  237. }
  238. }
Success #stdin #stdout 0.01s 131200KB
stdin
Standard input is empty
stdout
Точное значение интеграла: 60
<<<Метод трапеции>>>
  Разбиение	|	Интеграл	|	Абс. ошибка		|	Порядок
	10	|	60.1200000000001	|	0.47999999999999	|	 -------------
	20	|	60.0300000000001	|	0.120000000000054	|	3.9999999999931
	40	|	60.0074999999998	|	0.0300000000000651	|	4.000000000126
	80	|	60.0018749999998	|	0.00749999999978002	|	4.0000000004169
	160	|	60.0004687500009	|	0.0018749999997496	|	3.999999991375
	320	|	60.0001171875009	|	0.000468750000948148	|	3.9999999759893



Точное значение интеграла: 60
<<<Метод трапеции с поправкой Эйлера>>>
  Разбиение	|	Интеграл	|	Абс. ошибка		|	Порядок
	10	|	60.0000000000001	|	7.105427357601E-15	|	 -------------
	20	|	60.0000000000001	|	5.6843418860808E-14	|	0.8888888888889
	40	|	59.9999999999998	|	6.3948846218409E-14	|	0.2903225806452
	80	|	59.9999999999998	|	2.20268248085631E-13	|	0.8857142857143
	160	|	60.0000000000009	|	2.48689957516035E-13	|	0.2631578947368
	320	|	60.0000000000009	|	9.45021838560933E-13	|	1.0075757575758
Оценка Рунге для метода трапеций с eps = 0.00025
Количество точек: 160
Значение интеграла: 22.8304340724672

Оценка Рунге для метода трапеций с eps = 1E-10
Количество точек: 20
Значение интеграла: 22.8302557110943