Информатика: Функции — различия между версиями

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
Строка 2: Строка 2:
 
'''[[Лебедев Станислав]]''' <div class="mw-collapsible-content">
 
'''[[Лебедев Станислав]]''' <div class="mw-collapsible-content">
  
'''Описание программы''': программа позволяет сложить, умножить, возвести одну в степень другой две таблично заданные функции, а также линейно аппроксимировать результат. Чтение и вывод происходит через файл.
+
'''Описание программы''': программа позволяет сложить, умножить, возвести одну в степень другой две таблично заданные функции, а также линейно аппроксимировать результат. Чтение и вывод происходит через файл.<br />
 
'''Пояснения к алгоритму''':
 
'''Пояснения к алгоритму''':
 
#  Прочитанные из файла функции нужно отсортировать.
 
#  Прочитанные из файла функции нужно отсортировать.

Версия 16:34, 17 декабря 2015

Лебедев Станислав

Описание программы: программа позволяет сложить, умножить, возвести одну в степень другой две таблично заданные функции, а также линейно аппроксимировать результат. Чтение и вывод происходит через файл.
Пояснения к алгоритму:

  1. Прочитанные из файла функции нужно отсортировать.
  2. Найти совместную область определения, то есть, найти такой диапозон чисел, границы которого совпадали бы с границами начальных областей определений и/или могли быть на них интерполированны.
  3. Создать третью фунцию, со следующими свойствами : область опеределения состоит только из точек, пренадлежащих совместной области опредлений, каждая точка области значений является результатом нужной операции над точкой области значений одной из фунцкций и,либо интерполированной точкой по другой функции,либо,если есть возможность,точным значением.

<syntaxhighlight lang="cpp" line start="1" enclose="div">

  1. include <iostream>
  2. include <math.h>
  3. include <cstring>
  4. include <cmath>
  5. include <malloc.h>
  6. include <fstream>

using namespace std;

double base(double x) //базовая функция ( если задавать через шаг и начальный х {

   return x;

}

struct ap //две одинаковые структуры это нехорошо,коненчо,но зато наглядно... {

   double k,b;

};

struct fun //один столбик в таблице функции {

   double x,y;

};

struct sf //структура нужная, для возражеия значений из функции "prepare" класса F {

   int i1,i2,e1,e2;
   double glength, gfirstx, glastx;

};

double intr(double x1,double x2,double x,double y1,double y2) // линенейная интерполяция {

   return ( ((x-x1)/(x2-x1)) * (y2-y1) + y1 );

}

ap aproks(fun b [],int n) //линейная аппроксимация {

   ap r;
   double xy = 0,x = 0,y = 0,sqx = 0,xsq = 0;
   for (int i = 0; i < n; i++)                                 //вычисление коэффицентов
   {
       xy  += b[i].x*b[i].y;
       x   += b[i].x;
       y   += b[i].y;
       sqx += b[i].x*b[i].x;
       xsq += b[i].x;
   }
   xsq *= xsq;
   r.k = (n*xy - x*y)/(n*sqx - xsq);                       //использование формул
   r.b = (y - r.k*x)/n;
   return r;

}

class F { private:

   int length;
   double firstx, step, lastx;
   fun *a;

public:

   F(){}
   F(int l,double f,double s)                              //конструктор, создающий фунцию по длине,первоиу элементу,шагу по х, y вычисляется по базовой функции
   {
       if (l >= 0)
         a = new fun [l];
       firstx = f;
       length = l;
       step = s;
       lastx = firstx+(length - 1)*step;


       for (int i = 0;i < length; i ++)
       {
           a[i].y = base(firstx + i*step);
           a[i].x = firstx + i*step;
       }
   }
   F (fun b[],int l)                                   //конструктор для создания фунции с уже известными областями определния и значений
   {
       length = l;
       a = new fun [l];
       for (int i = 0; i < l;i++)
           a[i] = b[i];
       for (int i = 0; i < l;i++)
           for (int j = 0; j < (l - 1); j++)
               if (a[j].x > a[j + 1].x)
               {
                   fun tmp = a[j];
                   a[j] = a[j + 1];
                   a[j + 1] = a[j];
               }
       firstx = a[0].x;
       lastx = a[length - 1].x;
   }
   void addpar (double k, double b, int l, fun z[] )                           //позволяет создать и заполнить переданным массивом поле объекта класса
   {
       a = new fun [l];
       for (int i = 0; i < l; i++)
       {
           a[i].y = k*z[i].x + b;
           a[i].x = z[i].x;
       }
       length = l;
   }
   double getelx(int i)                                //возращает значение из поля "х" iого элемента
   {
       return a[i].x;
   }


   double getely(int i)                               //возращает значение из поля "х" iого элемента
   {
       return a[i].y;
   }
   int getlength()                                 //возращает размер области определения функции(в точках)
   {
       return length;
   }
   void FOut()                                     //выводит функцию на экран
   {
     cout << "   x         y" << endl;
     for (int i = 0;i < length; i ++)
         cout << "   " << a[i].x << "         " << a[i].y << endl;
     cout << endl;
   }


   int pfind(double x)const                        //возращает либо номер элемента,идущщий перед элементом, большим,чем х; в случае нахождения равного, возращает число, противоположное номеру следующего элемента(иначе может вернуться нуль,а нуль знака не имееет)
   {
       for (int i = 0; i < length-1; i++ )
       {
           if (((a[i].x < x) && (a[i + 1].x > x)))
               return (i + 1);
           else
               // чтобы иметь возможность проанализировать полученное значение функции,мы должны понимать, было найденно равное или промежуточное значение. "флагом" равных значений является знак минус,но так у нуля нет знака,то приходиться все сдвигать на 1
               if (a[i].x == x)
                 return -(i + 1);
               else
                   if (a[i + 1].x == x)
                       return -(i + 2);
       }

// cerr << "fail!!" << endl;

       return -1;
   }
   sf prepare(F &x)const                                      //"подготовка" функций к бинарной операции (нахождение совместной области определения
   {
       sf r;
       if (a[0].x > x.a[0].x)
       {
           r.gfirstx = a[0].x;
           r.i1 = 0;
           r.i1 = 0;
           double k = x.pfind(a[0].x);
           if (k < 0)
               r.i2 = -k - 1;
           else
               r.i2 = (k - 1) + 1;
       }
       else
       {
           r.gfirstx = x.a[0].x;
           double k = pfind(x.a[0].x);
           if (k < 0)
               r.i1 = -k - 1;
           else
               r.i1 = (k - 1) + 1;
           r.i2 = 0;
       }
       if (a[length - 1].x < x.a[x.length - 1].x)
       {
           r.glastx = a[length - 1].x;
           r.e1 = length - 1;
           double k = x.pfind(r.glastx);
           if (k < 0)
               r.e2 = -k - 1;
           else
               r.e2 = (k - 1) - 1;
       }
       else
       {
           r.glastx = x.a[x.length - 1].x;
           double k = pfind(r.glastx);
           if (k < 0)
               r.e1 = -k - 1;
           else
               r.e1 = (k - 1) + 1;
           r.e2 = x.length - 1;
       }
       r.glength = length + x.length - r.i1 - (length - (r.e1 + 1)) - r.i2 - (x.length - (r.e2 + 1));
       return r;
   }
   void ad (fun b[],int l)                                  //присвоить массиву объекта класса F значения массива b
   {
       length = l;
       a = new fun [l];
       for (int i = 0; i < l;i++)
           a[i] = b[i];
       firstx = a[0].x;
       lastx = a[length - 1].x;
   }
   fun *geta()                                         //получения указателя на начало массива в поле класса
   {
       return a;
   }
   F operator +(F &x) const                               //сложение двух функций
   {
       int i1, e1, i2, e2, kk = 0;
       double gfirstx, glastx, glength;
       if (((x.lastx < firstx) && (x.firstx < firstx)) || ((lastx < x.firstx) && (firstx < x.firstx)))
       {
           cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
           F fl(-1,0,0);
           return fl;
       }
       sf r = prepare(x);
       F tmp(r.glength,r.gfirstx,r.glastx);
       for (int i = 0; i <= (r.e1 - r.i1); i++)
       {
           tmp.a[i].x = a[i + r.i1].x;            //поправка,введенная таким образом,чтобы номер,с которого начинается отсчет был первым в новой области определения
           int ii = x.pfind(tmp.a[i].x);
           if (ii < 0)
               tmp.a[i].y = x.a[-ii - 1].y + a[i + r.i1].y;
           else
               tmp.a[i].y = intr(x.a[ii - 1].x , x.a[ii + 1].x , tmp.a[i].x , x.a[ii].y , x.a[ii + 1].y) + a[i + r.i1].y;
       }
       for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
       {
           int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
           if (ii >= 0)
           {
               tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
               tmp.a[i - kk].y = intr (a[ii - 1].x , a[(ii - 1) + 1].x , tmp.a[i - kk].x , a[ii - 1].y, a[(ii - 1) + 1].y) + x.a[i - (r.e1 - r.i1 + 1) + r.i2].y;
           }
           else
           {
               kk++;
               glength --;
               tmp.length --;
           }
       }
       for (int i = 0; i < glength; i++)
           for (int j = 0; j < glength - 1; j++)
           if (tmp.a[j].x > tmp.a[j + 1].x)
           {
               fun t = tmp.a[j];
               tmp.a[j] = tmp.a[j + 1];
               tmp.a[j + 1] = t;
           }
       return tmp;

}

   F operator *(F & x) const                                         //умножение двух функций
   {
       int i1, e1, i2, e2, kk = 0;
       double gfirstx, glastx, glength;
       if (((x.lastx < firstx) && (x.firstx < firstx)) || ((x.firstx < lastx) && (firstx < x.firstx)))
       {
           cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
           F fl(-1,0,0);
           return fl;
       }
       sf r = prepare(x);
       F tmp(r.glength,r.gfirstx,r.glastx);
       for (int i = 0; i <= (r.e1 - r.i1); i++)
       {
           tmp.a[i].x = a[i + r.i1].x;
           int ii = x.pfind(tmp.a[i].x);
           if (ii < 0)
               tmp.a[i].y = x.a[-ii - 1].y * a[i + r.i1].y;
           else
               tmp.a[i].y = intr(x.a[ii - 1].x , x.a[ii + 1].x , tmp.a[i].x , x.a[ii].y , x.a[ii + 1].y) * a[i + r.i1].y;
       }
       for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
       {
           int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
           if (ii >= 0)
           {
               tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
               tmp.a[i - kk].y = intr (a[ii - 1].x , a[(ii - 1) + 1].x , tmp.a[i - kk].x , a[ii - 1].y, a[(ii - 1) + 1].y) * x.a[i - (r.e1 - r.i1 + 1) + r.i2].y;
           }
           else
           {
               kk++;
               glength --;
               tmp.length --;
           }
       }
       for (int i = 0; i < glength; i++)
           for (int j = 0; j < glength - 1; j++)
           if (tmp.a[j].x > tmp.a[j + 1].x)
           {
               fun t = tmp.a[j];
               tmp.a[j] = tmp.a[j + 1];
               tmp.a[j + 1] = t;
           }
       return tmp;
   }
   F operator ^(F & x) const                                  //возведение функции слева от оператора в степень функции справа от оператора
   {
       int i1, e1, i2, e2, kk = 0;
       double gfirstx, glastx, glength;
       if (((x.lastx < firstx) && (x.firstx < firstx)) || ((x.firstx < lastx) && (firstx < x.firstx)))
       {
           cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
           F fl(-1,0,0);
           return fl;
       }
       sf r = prepare(x);
       F tmp(r.glength,r.gfirstx,r.glastx);
       for (int i = 0; i <= (r.e1 - r.i1); i++)
       {
           tmp.a[i].x = a[i + r.i1].x;
           int ii = x.pfind(tmp.a[i].x);
           if (ii < 0)
               tmp.a[i].y = pow(x.a[-ii - 1].y, a[i + r.i1].y);
           else
               tmp.a[i].y = pow(intr(x.a[ii - 1].x , x.a[ii + 1].x , tmp.a[i].x , x.a[ii].y , x.a[ii + 1].y), a[i + r.i1].y);
       }
       for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
       {
           int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
           if (ii >= 0)
           {
               tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
               tmp.a[i - kk].y = pow(intr (a[ii - 1].x , a[(ii - 1) + 1].x , tmp.a[i - kk].x , a[ii - 1].y, a[(ii - 1) + 1].y), x.a[i - (r.e1 - r.i1 + 1) + r.i2].y);
           }
           else
           {
               kk++;
               glength --;
               tmp.length --;
           }
       }
       for (int i = 0; i < glength; i++)
           for (int j = 0; j < glength - 1; j++)
           if (tmp.a[j].x > tmp.a[j + 1].x)
           {
               fun t = tmp.a[j];
               tmp.a[j] = tmp.a[j + 1];
               tmp.a[j + 1] = t;
           }
       return tmp;
   }

};

int main() {

  /*
   F f1(5,-2,1.5);
   F f2(30,-10,0.5);
   F f3, f4;
   f1.FOut();
   f2.FOut();
   f3 = f1 + f2;
   f3.FOut();
   f4 = f1 * f2;
   f4.FOut();
   cout << " ________" << endl;
  • /
   char vc, s[255], ce;
   ifstream infile;
   int n;
   fun *a;
   F f5,f6,f7,f8,f9;
   while(true)
   {
   start :
       system("cls");
       cout << "1 - Vvesti 1uu func"            << endl;
       cout << "2 - Vvesti 2uu func"            << endl;
       cout << "3 - Sloshit'"                   << endl;
       cout << "4 - Umnozhit'"                  << endl;
       cout << "5 - Vozvesti v stepen'"         << endl;
       cout << "6 - Aproximirovat'"             << endl;
       cout << "7 - Zapics' v file func"        << endl;
       cout << "8 - Zapics' v file aprok fun"   << endl;
       cout << "0 - Vihod"                      << endl;
       cin  >> vc;
       switch (vc)
       {
           case '0':
               return 0 ;
           case '1':
               {
               system("cls");
               strcpy(s,"");
               delete []a;
               a = NULL;
               cout << "Vvedite imya fila" << endl;
               cin >> s;
               strcat(s, ".txt");
               infile.open(s);
               infile >> n;
               a = new fun [n];
               for(int i = 0; i < n; i ++)
                   infile >> a[i].x >> a[i].y;
               f5.ad(a,n);
               f5.FOut();
               infile.close();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
               }
           case '2':
               {
               system("cls");
               strcpy(s,"");
               delete []a;
               a = NULL;
               cout << "Vvedite imya fila" << endl;
               cin >> s;
               strcat(s, ".txt");
               infile.open(s);
               infile >> n;
               a = new fun[n];
               for(int i = 0; i < n; i ++)
                   infile >> a[i].x >> a[i].y;
               f6.ad(a,n);
               f6.FOut();
               infile.close();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
               }
           case '3':
               system("cls");
               f5.FOut();
               f6.FOut();
               f7 = f5 + f6;
               f7.FOut();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
           case '4':
               system("cls");
               f5.FOut();
               f6.FOut();
               f7 = f5 * f6;
               f7.FOut();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
           case '5':
               system("cls");
               f5.FOut();
               f6.FOut();
               f7 = f5 ^ f6;
               f7 = f5 ^ f6;
               f7.FOut();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
           case '6':
           {
               system("cls");
               ap tmp = aproks(f7.geta(), f7.getlength());
               f8.addpar(tmp.k, tmp.b, f7.getlength(), f7.geta());
               f8.FOut();
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
           }
           case '7':
           {
               system("cls");
               strcpy(s,"");
               cout << "Vvedite imya fila" << endl;
               cin >> s;
               strcat(s, ".txt");
               ofstream outfile(s);
               outfile << "x           y" << endl;
               for (int i = 0; i < f7.getlength(); i ++)
                   outfile << f7.getelx(i) << "           " << f7.getely(i) << endl;
               cout << "done" << endl;
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
           }
           case '8':
               system("cls");
               strcpy(s,"");
               cout << "Vvedite imya fila" << endl;
               cin >> s;
               strcat(s, ".txt");
               ofstream outfile(s);
               outfile << "x           y" << endl;
               for (int i = 0; i < f8.getlength(); i ++)
                   outfile << f8.getelx(i) << "           " << f8.getely(i) << endl;
               cout << "done" << endl;
               cout << "Nazhmite \"b\" chotibi viti" << endl;
               cin >> ce;
               while (true)
               if (ce == 'b')
                   goto start;
       }
   }
   return 0;
}