Advertisement
Toliak

proga

Apr 7th, 2019
363
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.46 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2.  
  3. #include <math.h>
  4. #include <stdio.h>
  5.  
  6. #define MAX(x, y) ((x) > (y) ? (x) : (y))
  7. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  8.  
  9. #define EPSILON 0.000001
  10.  
  11. // f0 = arctg(x)
  12. double f0(double x)
  13. {
  14.     return atan(x);
  15. }
  16.  
  17. // f1 = ch(x)
  18. double f1(double x)
  19. {
  20.     return cosh(x);
  21. }
  22.  
  23. // f2 = 1/(1+x^2)
  24. double f2(double x)
  25. {
  26.     return 1 / (1 + x * x);
  27. }
  28.  
  29. // Метод левых прямоугольников
  30. // Принимает: начало, конец, количество отрезков, указатель на функцию
  31. double method0(double _start, double _end, unsigned long partsAmount, double (*function)(double))
  32. {
  33.     // Упорядочим начало и конец
  34.     double start = MIN(_start, _end);
  35.     double end = MAX(_start, _end);
  36.  
  37.     // Длина отрезка
  38.     double partSize = (end - start) / partsAmount;
  39.     double result = 0;
  40.     for (double x = start; x < end; x += partSize) {
  41.         result += function(x) * partSize;
  42.     }
  43.  
  44.     return result;
  45. }
  46.  
  47. // Метод правых прямоугольников
  48. // Принимает: начало, конец, количество отрезков, указатель на функцию
  49. double method1(double _start, double _end, unsigned long partsAmount, double (*function)(double))
  50. {
  51.     // Упорядочим начало и конец
  52.     double start = MIN(_start, _end);
  53.     double end = MAX(_start, _end);
  54.  
  55.     // Длина отрезка
  56.     double partSize = (end - start) / partsAmount;
  57.     double result = 0;
  58.     for (double x = start; x < end; x += partSize) {
  59.         result += function(x + partSize) * partSize;
  60.     }
  61.  
  62.     return result;
  63. }
  64.  
  65. // Метод центральных прямоугольников
  66. // Принимает: начало, конец, количество отрезков, указатель на функцию
  67. double method2(double _start, double _end, unsigned long partsAmount, double (*function)(double))
  68. {
  69.     // Упорядочим начало и конец
  70.     double start = MIN(_start, _end);
  71.     double end = MAX(_start, _end);
  72.  
  73.     // Длина отрезка
  74.     double partSize = (end - start) / partsAmount;
  75.     double result = 0;
  76.     for (double x = start; x < end; x += partSize) {
  77.         result += (function(x) + function(x + partSize)) / 2 * partSize;
  78.     }
  79.  
  80.     return result;
  81. }
  82.  
  83. // Формула Симпсона
  84. // Принимает: начало, конец, количество отрезков, указатель на функцию
  85. double method3(double _start, double _end, unsigned long partsAmount, double (*function)(double))
  86. {
  87.     // Упорядочим начало и конец
  88.     double start = MIN(_start, _end);
  89.     double end = MAX(_start, _end);
  90.  
  91.     // Длина отрезка
  92.     double partSize = (end - start) / partsAmount;
  93.     double result = 0;
  94.     for (double x = start; x < end; x += partSize) {
  95.         result += partSize/6 * (function(x) + 4 * function((2 * x + partSize) / 2) + function(x + partSize));
  96.     }
  97.  
  98.     return result;
  99. }
  100.  
  101. int main()
  102. {
  103.     //
  104.     double start, end;
  105.     unsigned int methodIndex;
  106.     printf("Enter X start: ");
  107.     scanf("%lf", &start);
  108.     printf("Enter X end: ");
  109.     scanf("%lf", &end);
  110.     printf("Available methods: \n\t0: left rectangles\n\t1: center rectangles\n\t");
  111.     printf("2: right rectangles\n\t3: Simpson's formula\n");
  112.     printf("Enter method: ");
  113.     scanf("%d", &methodIndex);
  114.  
  115.     // Указатель на функцию метода
  116.     double (*method)(double, double, unsigned long, double(*)(double));
  117.     switch (methodIndex) {
  118.         case 0: {
  119.             method = method0;
  120.             break;
  121.         }
  122.         case 1: {
  123.             method = method1;
  124.             break;
  125.         }
  126.         case 2: {
  127.             method = method2;
  128.             break;
  129.         }
  130.         default: {
  131.             method = method3;
  132.             break;
  133.         }
  134.     }
  135.  
  136.     // Формируем массив из указателей на функции (для удобства обхода)
  137.     double (*functions[3])(double) = {f0, f1, f2};
  138.     // Массив из названий функций
  139.     const char *functionsName[3] = {
  140.         "arctg(x)",
  141.         "ch(x)",
  142.         "1 / (1 + x^2)",
  143.     };
  144.  
  145.     for (unsigned int i = 0; i < 3; i++) {
  146.         unsigned long partsAmount = 100;           // Начальное количество отрезков
  147.         unsigned long partsAdd = 100;           // Прирост отрезков
  148.  
  149.         // Предыдущий результат (сохраняем для определения погрешности)
  150.         double prevResult = method(start, end, partsAmount+=partsAdd, functions[i]);
  151.         // Текущий результат
  152.         double result = method(start, end, partsAmount+=partsAdd, functions[i]);
  153.  
  154.         // Пока абсолютная разница между результатами больше эпсилон - увеличиваем количество отрезков
  155.         while (fabsl(prevResult - result) > EPSILON) {
  156.             prevResult = result;
  157.             result = method(start, end, partsAmount+=partsAdd, functions[i]);
  158.         }
  159.  
  160.         printf("\nFunction: %s\n", functionsName[i]);
  161.         printf("Result: %lf\n", result);
  162.         printf("Delta: %lf\n", fabs(prevResult - result));
  163.         printf("Parts amount: %lu\n", partsAmount);
  164.     }
  165.  
  166.     return 0;
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement