Advertisement
Guest User

poly 6:26 25.06

a guest
Jun 24th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.32 KB | None | 0 0
  1. #include <iostream>
  2. #include <assert.h>
  3. #include <cmath>
  4. #define double_NULL 0.00000001
  5. #define POINTS 4
  6.  
  7. using namespace std;
  8.  
  9. class node { // узел списка, в котором хранится моном и указатель на следующий
  10. public:
  11.     int exponent;
  12.     double number;
  13.    
  14.     node* next;
  15. };
  16.  
  17. class polynom {
  18. public:
  19.     polynom() { head = NULL; };
  20.     polynom(double numb, int exp) { head = AddHead(NULL, numb, exp); head->next = NULL; }
  21.     ~polynom() { head = Delete(head); }
  22.     polynom operator +(polynom &a);         // сложение полиномов
  23.     polynom operator *(polynom &a);         // умножение полиномов
  24.     polynom operator *(double x);           // умножение полинома на double
  25.     polynom &operator =(const polynom &a);  // присваивание
  26.     polynom &operator +=(const polynom &a); // плюс присвоить полином
  27.     polynom &operator *=(const polynom &a); // умножить присвоить полином
  28.     polynom &operator *= (double x);        // умножить присвоить полином (double)
  29.     void NewElement(double numb, int exp);  // добавить новый член в полином ПОТОМ УБРАТЬ
  30.     double Point(double x);                 // вычислить значение в точке
  31.     friend ostream &operator <<(ostream &out, const polynom &x);
  32. private:
  33.     node *head;
  34.     node *AddHead(node *h, double numb, int exp);    // добавить голову
  35.     node *DelHead(node *h);                          // удалить голову
  36.     node *Delete(node *h);                           // очистить список h
  37.     void AddAfter(node *x, double n, int p);         // добавить элемент после x
  38.     void DelAfter(node *x);                          // удалить элемент после x
  39.     node *Unite(node *const a, node *b);             // сложение двух полиномов
  40.     node *Multiple(node *const a, node *b);          // умножение двух полиномов
  41.     node *FindInsert(node *a, double numb, int exp); // найти место в списке a и вставить его
  42.     node *Copy(node *a);                             // скопировать список a, возвращает указатель на новый
  43. };
  44.  
  45. class point { // точка для сетки значений
  46. public:
  47.     point(double _x = 0, double _y = 0) : x(_x), y(_y) {}
  48.     double x, y;
  49. };
  50.  
  51. /*----------------DEAL WITH NET START----------------*/
  52. void CreateNet(point *x, int quantity, polynom &c, double a, double b) {
  53.     double shift = (b - a)/(quantity - 1);
  54.    
  55.     for (int i = 0; i < quantity - 1; i++) {
  56.         x[i].x = a + shift*i;
  57.         x[i].y = c.Point(x[i].x);
  58.     }
  59.     x[quantity - 1].x = b;
  60.     x[quantity - 1].y = c.Point(x[quantity - 1].x);
  61. }
  62.  
  63. void PrintNet(point *x, int quantity) {
  64.     for (int i = 0; i < quantity; i++)
  65.         cout << "x = " << x[i].x << ", y = " << x[i].y << endl;
  66. }
  67. /*----------------DEAL WITH NET END----------------*/
  68.  
  69. class lagrange {
  70. public:
  71.     lagrange(point *net, int quantity);
  72.     double Result(double z); // поиск значения в точке z
  73.     void PrintNet(int quantity, double a, double b);
  74.     friend ostream &operator <<(ostream &out, const lagrange &l);
  75. private:
  76.     polynom *x;
  77.     polynom Base(point *net, int quantity, int i); // поиск базисного многочлена умноженного на y(i)
  78. };
  79.  
  80. class newton {
  81. public:
  82.     newton(point *net, int quantity);
  83.     double Result(double z);
  84.     void PrintNet(int quantity, double a, double b);
  85.     friend ostream &operator <<(ostream &out, const newton &n);
  86. private:
  87.     polynom *x;
  88.     double *Diff1Stroke(point *net, int quantity); // возвращает массив разделенных разностей (первый элемент каждого столбца)
  89. };
  90.  
  91. /*-------------------------------------------PRIVATE PART START (POLYNOM)-------------------------------------------*/
  92. node *polynom::AddHead(node *h, double numb, int exp) { // добавить голову
  93.     node *p = new node;
  94.     p->number = numb;
  95.     p->next = h;
  96.     p->exponent = exp;
  97.     return p;
  98. }
  99.  
  100. node *polynom::DelHead(node *h) { // удалить голову
  101.     node *p = h->next;
  102.     delete h;
  103.     return p;
  104. }
  105.  
  106. double polynom::Point(double x) { // вычислить значение в точке
  107.     node *temp = this->head;
  108.     double res = temp->number;
  109.     int exp = temp->exponent;
  110.    
  111.     temp = temp->next;
  112.    
  113.     while (temp) {
  114.         if (exp - temp->exponent > 1) {
  115.             res *= x;
  116.             exp--;
  117.             continue;
  118.         }
  119.        
  120.         res *= x;
  121.         res += temp->number;
  122.         exp = temp->exponent;
  123.         temp = temp->next;
  124.     }
  125.    
  126.     while (exp > 0) {
  127.         res *= x;
  128.         exp--;
  129.     }
  130.    
  131.     return res;
  132. }
  133.  
  134. node *polynom::FindInsert(node *a, double numb, int exp) { // найти место в списке a и вставить его
  135.     if (a == NULL || a->exponent < exp) // если головы нет, или слово нужно вставить в начало списка, то добавляем голову
  136.         return AddHead(a, numb, exp);
  137.    
  138.     node *copy = a, *prev = copy; // создаем копию структуры и отстающ. счетчик
  139.    
  140.     while (copy != NULL) {
  141.         if (exp < copy->exponent) { // идем по структуре, пока степень больше тех, которые в списке, если больше, переходим к след. итерации цикла
  142.             prev = copy;
  143.             copy = copy->next;
  144.             continue;
  145.         }
  146.        
  147.         if (exp == copy->exponent) { // если член с такой степенью уже есть в списке, то прибавляем коэффициент, возвращ. голову
  148.             copy->number += numb;
  149.             if (fabs(copy->number) < double_NULL) {
  150.                 if (copy == a) {
  151.                     copy = DelHead(copy);
  152.                     a = copy;
  153.                 }
  154.                 else
  155.                     DelAfter(prev);
  156.             }
  157.            
  158.             return a;
  159.         }
  160.        
  161.         if (exp > copy->exponent) { // если степень меньше, то вставляем после prev
  162.             AddAfter(prev, numb, exp);
  163.             return a;
  164.         }
  165.     }
  166.    
  167.     AddAfter(prev, numb, exp);
  168.     return a;
  169. }
  170.  
  171. void polynom::AddAfter(node *x, double numb, int exp) { // добавить элемент после x
  172.     node *p = new node;
  173.     p->exponent = exp;
  174.     p->number = numb;
  175.     p->next = x->next;
  176.     x->next = p;
  177. }
  178.  
  179. void polynom::DelAfter(node *x) { // удалить элемент после x
  180.     node *p = x->next;
  181.     x->next = p->next;
  182.     delete p;
  183. }
  184.  
  185. node *polynom::Delete(node *h) { // очистить список h
  186.     node *temp;
  187.     while (h != NULL) {
  188.         temp = h->next;
  189.         delete h;
  190.         h = temp;
  191.     }
  192.    
  193.     return h;
  194. }
  195.  
  196. node *polynom::Copy(node *a) { // скопировать список a, возвращает указатель на новый
  197.     node *temp = NULL, *copy = NULL;
  198.    
  199.     if (a == NULL)
  200.         return NULL;
  201.    
  202.     temp = AddHead(temp, a->number, a->exponent);
  203.     copy = temp;
  204.     a = a->next;
  205.    
  206.     while (a != NULL) {
  207.         AddAfter(copy, a->number, a->exponent);
  208.         a = a->next;
  209.         copy = copy->next;
  210.     }
  211.    
  212.     return temp;
  213. }
  214.  
  215. node *polynom::Unite(node *const a, node *b) { // сложение двух полиномов
  216.     node *temp = Copy(a);
  217.    
  218.     while (b != NULL && temp != NULL) {
  219.         temp = FindInsert(temp, b->number, b->exponent); // НЕ НУЖЕН, ВСЕГО БУДЕТ ОДИН ЦИКЛ
  220.         b = b->next;
  221.     }
  222.     // + КОПИРОВАНИЕ В ХВОСТ
  223.     return temp;
  224. }
  225.  
  226. node *polynom::Multiple(node *const a, node *b) { // умножение двух полиномов
  227.     node *copy = NULL, *temp = NULL, *temp_copy;
  228.    
  229.     while (b != NULL) {
  230.         temp = Copy(a);
  231.         temp_copy = temp;
  232.        
  233.         while (temp_copy) { // НЕТ СЛОЖЕНИЯ В ЯВНОМ ВИДЕ, ВСЕГО БУДЕТ 2 ЦИКЛА (ОДИН ВЛОЖЕННЫЙ)
  234.             temp_copy->number *= b->number;
  235.             temp_copy->exponent += b->exponent;
  236.             temp_copy = temp_copy->next;
  237.         }
  238.        
  239.         copy = Unite(copy, temp);
  240.         Delete(temp);
  241.         b = b->next;
  242.     }
  243.    
  244.     return copy;
  245. }
  246. /*-------------------------------------------PRIVATE PART END (POLYNOM)-------------------------------------------*/
  247.  
  248. /*-------------------------------------------PUBLIC PART START (POLYNOM)-------------------------------------------*/
  249. polynom polynom::operator +(polynom &a) { // сложение полиномов
  250.     polynom x;
  251.    
  252.     x.head = x.Copy(a.head);
  253.     x += *this;
  254.    
  255.     return x;
  256. }
  257.  
  258. polynom polynom::operator *(polynom &a) { // умножение полиномов
  259.     polynom x;
  260.    
  261.     x.head = x.Copy(a.head);
  262.     x *= *this;
  263.    
  264.     return x;
  265. }
  266.  
  267. polynom polynom::operator *(double x) { // умножение полинома на double
  268.     polynom c;
  269.    
  270.     c.head = c.Copy(this->head);
  271.     c *= x;
  272.    
  273.     return c;
  274. }
  275.  
  276. polynom &polynom::operator =(const polynom &a) { // присваивание
  277.     if (&a != this) {
  278.         Delete(head);
  279.         head = Copy(a.head);
  280.     }
  281.    
  282.     return *this;
  283. }
  284.  
  285. polynom &polynom::operator +=(polynom const &a) { // плюс присвоить полином
  286.     if (this->head == NULL) {
  287.         this->head = Copy(a.head);
  288.         return *this;
  289.     }
  290.    
  291.     if (a.head == NULL)
  292.         return *this;
  293.    
  294.     head = Unite(head, a.head);
  295.    
  296.     return *this;
  297. }
  298.  
  299. polynom &polynom::operator *=(polynom const &a) { // умножить присвоить полином
  300.     if (a.head != NULL)
  301.         head = Multiple(head, a.head);
  302.    
  303.     return *this;
  304. }
  305.  
  306. polynom &polynom::operator *=(double x) { // умножить присвоить полином (double)
  307.     node *temp = this->head;
  308.    
  309.     while (temp) {
  310.         temp->number *= x;
  311.         temp = temp->next;
  312.     }
  313.    
  314.     return *this;
  315. }
  316.  
  317. ostream &operator <<(ostream &out, const polynom &x) {
  318.     node *temp = x.head;
  319.    
  320.     if (temp)
  321.         out << temp->number << "*x^" << temp->exponent << " ";
  322.     else
  323.         return out;
  324.     temp = temp->next;
  325.    
  326.     while (temp) {
  327.         out << (temp->number > 0 ? "+ " : "- ") << fabs(temp->number) << "*x^" << temp->exponent << " ";
  328.         temp = temp->next;
  329.     }
  330.     out << endl;
  331.    
  332.     return out;
  333. }
  334.  
  335. void polynom::NewElement(double numb, int exp) { // добавить новый член в полином
  336.     head = FindInsert(head, numb, exp);
  337. }
  338. /*-------------------------------------------PUBLIC PART END (POLYNOM)-------------------------------------------*/
  339.  
  340. /*-------------------------------------------START (LAGRANGE)-------------------------------------------*/
  341. polynom lagrange::Base(point *net, int quantity, int i) {
  342.     polynom c(1.0, 0), a, temp, reserve(1.0, 1);
  343.     double zn = 1.0;
  344.    
  345.     for (int j = 0; j < quantity; j++) // РАЗДЕЛИТЬ НА 2 ЦИКЛА
  346.         if (j != i) {
  347.             temp = reserve;
  348.             a.NewElement(-net[j].x, 0);
  349.             temp += a;
  350.             a.NewElement(net[j].x, 0);
  351.             c *= temp;
  352.             zn *= net[i].x - net[j].x;
  353.         }
  354.     zn = net[i].y/zn;
  355.     c *= zn;
  356.    
  357.     return c;
  358. }
  359.  
  360. lagrange::lagrange(point *net, int quantity) {
  361.     x = new polynom;
  362.    
  363.     for (int i = 0; i < quantity; i++)
  364.         *x += Base(net, quantity, i);
  365. }
  366.  
  367. double lagrange::Result(double z) {
  368.     return x->Point(z);
  369. }
  370.  
  371. void lagrange::PrintNet(int quantity, double a, double b) {
  372.     point lagr[quantity];
  373.    
  374.     CreateNet(lagr, quantity, *x, a, b);
  375.     ::PrintNet(lagr, quantity);
  376. }
  377.  
  378. ostream &operator <<(ostream &out, const lagrange &l) {
  379.     out << *(l.x) << endl;
  380.     return out;
  381. }
  382. /*-------------------------------------------END (LAGRANGE)-------------------------------------------*/
  383.  
  384. /*-------------------------------------------START (NEWTON)-------------------------------------------*/
  385. newton::newton(point *net, int quantity) {
  386.     double *diff = Diff1Stroke(net, quantity);
  387.     x = new polynom;
  388.     polynom temp(1.0, 0), res(1.0, 1);
  389.     x->NewElement(diff[0], 0);
  390.    
  391.     for (int i = 1; i < quantity; i++) {
  392.         res.NewElement(-net[i - 1].x, 0); // + ПЕРЕГРУЗКА ПОЛИНОМ + double
  393.         temp *= res;
  394.         *x += temp * diff[i];
  395.         res.NewElement(net[i - 1].x, 0);
  396.     }
  397. }
  398.  
  399. double *newton::Diff1Stroke(point *net, int quantity) {
  400.     double *c = new double[quantity];
  401.     double *result = new double[quantity]; // массив значений 1ой строки
  402.     int k = 0;
  403.    
  404.     for (int i = 0; i < quantity; i++) // заполняем столбец разделенных разностей 0го порядка
  405.         c[i] = net[i].y;
  406.     result[k] = c[k];
  407.     k++;
  408.    
  409.     for (int i = quantity; i > 0; i--) {
  410.         for (int j = 0; j < i - 1; j++) {
  411.             c[j] = (c[j + 1] - c[j])/(net[quantity - i + j + 1].x - net[j].x);
  412.         }
  413.         result[k++] = c[0];
  414.     }
  415.    
  416.     delete [] c;
  417.     return result; // ЧИСТИТЬ result
  418. }
  419.  
  420. double newton::Result(double z) {
  421.     return x->Point(z);
  422. }
  423.  
  424. void newton::PrintNet(int quantity, double a, double b) {
  425.     point newt[quantity];
  426.    
  427.     CreateNet(newt, quantity, *x, a, b);
  428.     ::PrintNet(newt, quantity);
  429. }
  430.  
  431. ostream &operator <<(ostream &out, const newton &n) {
  432.     out << *(n.x) << endl;
  433.     return out;
  434. }
  435. /*-------------------------------------------END (NEWTON)-------------------------------------------*/
  436.  
  437. int main() {
  438.     polynom x(5, 5);
  439.     polynom y(15, 9);
  440.    
  441.     x.NewElement(3, 4);
  442.     x.NewElement(2, 3);
  443.     x.NewElement(4, 2);
  444.    
  445.     y.NewElement(9, 8);
  446.     y.NewElement(6, 7);
  447.     y.NewElement(12, 6);
  448.    
  449.     cout << x;
  450.    
  451.     point a[POINTS];
  452.     CreateNet(a, POINTS, x, 0.5, 2.9);
  453.     PrintNet(a, POINTS);
  454.    
  455.     lagrange l(a, POINTS);
  456.     cout << l;
  457.    
  458.     newton n(a, POINTS);
  459.     cout << n;
  460. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement