constk

Solving non linear equations 1.0

Sep 15th, 2020
127
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <vector>
  5. #include <stdexcept>
  6.  
  7.  
  8.  
  9. struct Section {
  10.     double leftBorder;
  11.     double rightBorder;
  12. };
  13.  
  14.  
  15.  
  16. std::vector<Section> sections;
  17. std::vector<double> roots;
  18.  
  19.  
  20.  
  21. const double EPS = 0.001;
  22.  
  23.  
  24.  
  25. double f1(double x); // [0 ; 1] root is 0.1
  26. double f2(double x); // just y = x
  27. double f3(double x); // [1.5 ; 3.14] root is 2
  28. double f4(double x); // just y = sin(x)
  29. double f5(double x); // just x*x
  30.  
  31. typedef double (*pointFunc)(double x);
  32.  
  33.  
  34. double derivative(pointFunc f, double x);
  35. double doubleDerivative(pointFunc f, double x);
  36.  
  37.  
  38.  
  39. double halfDivisionMethod(pointFunc f, const Section & section);
  40. double chordMethod(pointFunc f, const Section & section);
  41. double newtonMethod(pointFunc f, const Section & section);
  42. double interationMethod(pointFunc f, const Section & section);
  43.  
  44. typedef double(*pointMethod)(pointFunc f, const Section & section);
  45.  
  46.  
  47.  
  48. int main() {
  49.     // Воод исходных данных и разбиение функции на интервалы (отделение корней)
  50.     const pointFunc f = f1;
  51.     int n = 0;
  52.     double leftBorder = 0.0;
  53.     double rightBorder = 0.0;
  54.  
  55.     initInput:
  56.     printf("Input left border: ");
  57.     scanf("%lf", &leftBorder);
  58.     printf("Input right border: ");
  59.     scanf("%lf", &rightBorder);
  60.     printf("Input amount of sections: ");
  61.     scanf("%d", &n);
  62.    
  63.     if (rightBorder <= leftBorder) {
  64.         puts("Error: incorrect input of section borders! Try again!\n");
  65.         goto initInput;
  66.     }
  67.     if (n <= 0) {
  68.         puts("Error: incorrect input amount of sections! Try again!\n");
  69.         goto initInput;
  70.     }
  71.  
  72.     double x = leftBorder;
  73.     double h = (rightBorder - leftBorder) / double(n);
  74.  
  75.     while (x < rightBorder)
  76.     {
  77.         if (f(x) * f(x + h) <= 0)
  78.             sections.push_back({ x, x + h });
  79.         x += h;
  80.     }
  81.  
  82.     if (sections.empty()) {
  83.         printf("Error: something went wrong trying to get sections.");
  84.         printf("Ensure equation have roots or increase N.");
  85.         getchar();
  86.         getchar();
  87.         exit(1);
  88.     }
  89.     puts("");
  90.  
  91.  
  92.  
  93.     // Выбор метода решения и вычисление корней
  94.     pointMethod method = NULL;
  95.     backToChoice:
  96.     puts("Choose method: ");
  97.     puts("Print 1 to use half division method.");
  98.     puts("Print 2 to use chord method.");
  99.     puts("Print 3 to use Newton method.");
  100.     puts("Print 4 to use iteration method.");
  101.     int choice = 0;
  102.     scanf("%d", &choice);
  103.     switch (choice)
  104.     {
  105.     case 1:
  106.         method = halfDivisionMethod;
  107.         break;
  108.     case 2:
  109.         method = chordMethod;
  110.         break;
  111.     case 3:
  112.         method = newtonMethod;
  113.         break;
  114.     case 4:
  115.         method = interationMethod;
  116.         break;
  117.     default:
  118.         puts("There is no such method! Choose again!\n");
  119.         goto backToChoice;
  120.     }
  121.  
  122.     while (!sections.empty()) {
  123.         try {
  124.             roots.push_back(method(f, sections.back()));
  125.         }
  126.         catch (std::runtime_error& e) {
  127.             printf("Error: %s", e.what());
  128.             getchar();
  129.             getchar();
  130.             exit(1);
  131.         }
  132.         sections.pop_back();
  133.     }
  134.     puts("");
  135.  
  136.  
  137.  
  138. // Вывод результатов и тестирование
  139. printf("Roots: ");
  140. for (int i = 0; i != roots.size(); ++i)
  141. printf("%f   ", roots.at(i));
  142. puts("\n");
  143.  
  144. while (!roots.empty()) {
  145.     double currentRoot = roots.back();
  146.     if (fabs(f(currentRoot)) > EPS*2)
  147.         printf("Test failed: %f is not root of the equation! f(%f) = %f\n", currentRoot, currentRoot, f(currentRoot));
  148.     else
  149.         printf("Test passed.\n");
  150.     roots.pop_back();
  151. }
  152. puts("");
  153.  
  154.  
  155.  
  156. // Конец программы
  157. puts("End of program. Press enter to exit.");
  158. getchar();
  159. getchar();
  160. return 0;
  161. }
  162.  
  163.  
  164. double f1(double x) {
  165.     return exp(x) - 10 * x;
  166. }
  167.  
  168. double f2(double x) {
  169.     return 2 * x;
  170. }
  171.  
  172. double f3(double x) {
  173.     return x * x - 5 * sin(x);
  174. }
  175.  
  176. double f4(double x)
  177. {
  178.     return sin(x);
  179. }
  180.  
  181. double f5(double x)
  182. {
  183.     return x*x;
  184. }
  185.  
  186.  
  187. double derivative(pointFunc f, double x)
  188. {
  189.     const double h = 0.005;
  190.     return (f(x) - f(x + h)) / h;
  191. }
  192.  
  193. double doubleDerivative(pointFunc f, double x)
  194. {
  195.     const double h = 0.005;
  196.     return (f(x + h) - 2 * f(x) + f(x - h)) / (h * h);
  197. }
  198.  
  199. double halfDivisionMethod(pointFunc f, const Section & section) {
  200.     int iterationsCounter = 0;
  201.     double a = section.leftBorder;
  202.     double b = section.rightBorder;
  203.     double x = (a + b) / 2.0;
  204.     double yLeft = f(a), yRight = f(b), yCenter = f(x);
  205.  
  206.     while (fabs(yRight - yLeft) > EPS  && iterationsCounter != 10000) {
  207.         if (yCenter * yRight < 0) {
  208.             a = x;
  209.             yLeft = f(a);
  210.         }
  211.         else {
  212.             b = x;
  213.             yRight = f(b);
  214.         }
  215.  
  216.         x = (a + b) / 2.0;
  217.         yCenter = f(x);
  218.         ++iterationsCounter;
  219.     }
  220.  
  221.     if (iterationsCounter == 10000) {
  222.         throw std::runtime_error("Half division method does not respond.");
  223.     }
  224.  
  225.     return x;
  226. }
  227.  
  228. double chordMethod(pointFunc f, const Section & section) {
  229.     int iterationsCounter = 0;
  230.     double a = section.leftBorder;
  231.     double b = section.rightBorder;
  232.     double result = 0.0;
  233.     double yLeft = f(a), yRight = f(b);
  234.  
  235.  
  236.     if ((yLeft*doubleDerivative(f ,a)) > 0)
  237.     {
  238.         while (fabs(b - ((b - a) / (yRight - yLeft))*yRight - b) > EPS && iterationsCounter != 100000)
  239.         {
  240.             b = b - ((b - a) / (yRight - yLeft))*yRight;
  241.             ++iterationsCounter;
  242.             yRight = f(b);
  243.         }
  244.         result = b;
  245.     }
  246.     else
  247.     {
  248.         while (fabs(a - ((b - a) / (yRight - yLeft))*yLeft - a) > EPS && iterationsCounter != 100000)
  249.         {
  250.             a = a - ((b - a) / (yRight - yLeft))*yLeft;
  251.             ++iterationsCounter;
  252.             yLeft = f(a);
  253.         }
  254.         result = a;
  255.     }
  256.  
  257.  
  258.     if (iterationsCounter == 100000) {
  259.         throw std::runtime_error("Chord method does not respond.");
  260.     }
  261.  
  262.     return result;
  263. }
  264.  
  265. double newtonMethod(pointFunc f, const Section & section)
  266. {
  267.     return 0.0;
  268. }
  269.  
  270. double interationMethod(pointFunc f, const Section & section)
  271. {
  272.     return 0.0;
  273. }
  274.  
RAW Paste Data