Информатика: Функции

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск

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

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

Пояснения к алгоритму:

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

Скачать можно тут.

  1 #include <iostream>
  2 #include <math.h>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <malloc.h>
  6 #include <fstream>
  7 
  8 using namespace std;
  9 
 10 double base(double x)                                        //базовая функция ( если задавать через шаг и начальный х
 11 {
 12     return x;
 13 }
 14 
 15 struct ap                                                   //две одинаковые структуры это нехорошо,коненчо,но зато наглядно...
 16 {
 17     double k,b;
 18 };
 19 
 20 struct fun                                                   //один столбик в таблице функции
 21 {
 22     double x,y;
 23 };
 24 
 25 struct sf                                                   //структура нужная, для возражеия значений из функции "prepare" класса F
 26 {
 27     int i1,i2,e1,e2;
 28     double glength, gfirstx, glastx;
 29 };
 30 
 31 double intr(double x1,double x2,double x,double y1,double y2)  // линенейная интерполяция
 32 {
 33     return ( ((x-x1)/(x2-x1)) * (y2-y1) + y1 );
 34 }
 35 
 36 ap aproks(fun b [],int n)                                       //линейная аппроксимация
 37 {
 38     ap r;
 39     double xy = 0,x = 0,y = 0,sqx = 0,xsq = 0;
 40     for (int i = 0; i < n; i++)                                 //вычисление коэффицентов
 41     {
 42         xy  += b[i].x*b[i].y;
 43         x   += b[i].x;
 44         y   += b[i].y;
 45         sqx += b[i].x*b[i].x;
 46         xsq += b[i].x;
 47     }
 48     xsq *= xsq;
 49 
 50     r.k = (n*xy - x*y)/(n*sqx - xsq);                       //использование формул
 51     r.b = (y - r.k*x)/n;
 52     return r;
 53 }
 54 
 55 class F
 56 {
 57 private:
 58     int length;
 59     double firstx, step, lastx;
 60     fun *a;
 61 public:
 62     F(){}
 63     F(int l,double f,double s)                              //конструктор, создающий фунцию по длине,первоиу элементу,шагу по х, y вычисляется по базовой функции
 64     {
 65         if (l >= 0)
 66           a = new fun [l];
 67         firstx = f;
 68         length = l;
 69         step = s;
 70         lastx = firstx+(length - 1)*step;
 71 
 72 
 73         for (int i = 0;i < length; i ++)
 74         {
 75             a[i].y = base(firstx + i*step);
 76             a[i].x = firstx + i*step;
 77         }
 78 
 79     }
 80 
 81     F (fun b[],int l)                                   //конструктор для создания фунции с уже известными областями определния и значений
 82     {
 83         length = l;
 84         a = new fun [l];
 85         for (int i = 0; i < l;i++)
 86             a[i] = b[i];
 87 
 88         for (int i = 0; i < l;i++)
 89             for (int j = 0; j < (l - 1); j++)
 90                 if (a[j].x > a[j + 1].x)
 91                 {
 92                     fun tmp = a[j];
 93                     a[j] = a[j + 1];
 94                     a[j + 1] = a[j];
 95                 }
 96 
 97         firstx = a[0].x;
 98         lastx = a[length - 1].x;
 99     }
100 
101     void addpar (double k, double b, int l, fun z[] )                           //позволяет создать и заполнить переданным массивом поле объекта класса
102     {
103         a = new fun [l];
104         for (int i = 0; i < l; i++)
105         {
106             a[i].y = k*z[i].x + b;
107             a[i].x = z[i].x;
108         }
109         length = l;
110     }
111 
112     double getelx(int i)                                //возращает значение из поля "х" iого элемента
113     {
114         return a[i].x;
115     }
116 
117 
118     double getely(int i)                               //возращает значение из поля "х" iого элемента
119     {
120         return a[i].y;
121     }
122 
123     int getlength()                                 //возращает размер области определения функции(в точках)
124     {
125         return length;
126     }
127 
128     void FOut()                                     //выводит функцию на экран
129     {
130       cout << "   x         y" << endl;
131       for (int i = 0;i < length; i ++)
132           cout << "   " << a[i].x << "         " << a[i].y << endl;
133       cout << endl;
134     }
135 
136 
137     int pfind(double x)const                        //возращает либо номер элемента,идущщий перед элементом, большим,чем х; в случае нахождения равного, возращает число, противоположное номеру следующего элемента(иначе может вернуться нуль,а нуль знака не имееет)
138     {
139         for (int i = 0; i < length-1; i++ )
140         {
141             if (((a[i].x < x) && (a[i + 1].x > x)))
142                 return (i + 1);
143             else
144                 // чтобы иметь возможность проанализировать полученное значение функции,мы должны понимать, было найденно равное или промежуточное значение. "флагом" равных значений является знак минус,но так у нуля нет знака,то приходиться все сдвигать на 1
145                 if (a[i].x == x)
146                   return -(i + 1);
147                 else
148                     if (a[i + 1].x == x)
149                         return -(i + 2);
150         }
151 //        cerr << "fail!!" << endl;
152         return -1;
153     }
154 
155     sf prepare(F &x)const                                      //"подготовка" функций к бинарной операции (нахождение совместной области определения
156     {
157         sf r;
158         if (a[0].x > x.a[0].x)
159         {
160             r.gfirstx = a[0].x;
161             r.i1 = 0;
162             r.i1 = 0;
163             double k = x.pfind(a[0].x);
164             if (k < 0)
165                 r.i2 = -k - 1;
166             else
167                 r.i2 = (k - 1) + 1;
168         }
169         else
170         {
171             r.gfirstx = x.a[0].x;
172             double k = pfind(x.a[0].x);
173             if (k < 0)
174                 r.i1 = -k - 1;
175             else
176                 r.i1 = (k - 1) + 1;
177             r.i2 = 0;
178         }
179 
180         if (a[length - 1].x < x.a[x.length - 1].x)
181         {
182             r.glastx = a[length - 1].x;
183             r.e1 = length - 1;
184             double k = x.pfind(r.glastx);
185             if (k < 0)
186                 r.e2 = -k - 1;
187             else
188                 r.e2 = (k - 1) - 1;
189         }
190         else
191         {
192             r.glastx = x.a[x.length - 1].x;
193             double k = pfind(r.glastx);
194             if (k < 0)
195                 r.e1 = -k - 1;
196             else
197                 r.e1 = (k - 1) + 1;
198             r.e2 = x.length - 1;
199         }
200         r.glength = length + x.length - r.i1 - (length - (r.e1 + 1)) - r.i2 - (x.length - (r.e2 + 1));
201 
202         return r;
203     }
204 
205     void ad (fun b[],int l)                                  //присвоить массиву объекта класса F значения массива b
206     {
207         length = l;
208         a = new fun [l];
209         for (int i = 0; i < l;i++)
210             a[i] = b[i];
211         firstx = a[0].x;
212         lastx = a[length - 1].x;
213     }
214 
215     fun *geta()                                         //получения указателя на начало массива в поле класса
216     {
217         return a;
218     }
219 
220     F operator +(F &x) const                               //сложение двух функций
221     {
222         int i1, e1, i2, e2, kk = 0;
223         double gfirstx, glastx, glength;
224 
225         if (((x.lastx < firstx) && (x.firstx < firstx)) || ((lastx < x.firstx) && (firstx < x.firstx)))
226         {
227             cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
228             F fl(-1,0,0);
229             return fl;
230         }
231         sf r = prepare(x);
232         F tmp(r.glength,r.gfirstx,r.glastx);
233         for (int i = 0; i <= (r.e1 - r.i1); i++)
234         {
235             tmp.a[i].x = a[i + r.i1].x;            //поправка,введенная таким образом,чтобы номер,с которого начинается отсчет был первым в новой области определения
236             int ii = x.pfind(tmp.a[i].x);
237             if (ii < 0)
238                 tmp.a[i].y = x.a[-ii - 1].y + a[i + r.i1].y;
239             else
240                 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;
241         }
242         for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
243         {
244             int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
245             if (ii >= 0)
246             {
247                 tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
248                 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;
249             }
250             else
251             {
252                 kk++;
253                 glength --;
254                 tmp.length --;
255             }
256         }
257 
258         for (int i = 0; i < glength; i++)
259             for (int j = 0; j < glength - 1; j++)
260             if (tmp.a[j].x > tmp.a[j + 1].x)
261             {
262                 fun t = tmp.a[j];
263                 tmp.a[j] = tmp.a[j + 1];
264                 tmp.a[j + 1] = t;
265             }
266 
267         return tmp;
268 }
269 
270     F operator *(F & x) const                                         //умножение двух функций
271     {
272         int i1, e1, i2, e2, kk = 0;
273         double gfirstx, glastx, glength;
274 
275         if (((x.lastx < firstx) && (x.firstx < firstx)) || ((x.firstx < lastx) && (firstx < x.firstx)))
276         {
277             cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
278             F fl(-1,0,0);
279             return fl;
280         }
281 
282         sf r = prepare(x);
283         F tmp(r.glength,r.gfirstx,r.glastx);
284 
285         for (int i = 0; i <= (r.e1 - r.i1); i++)
286         {
287             tmp.a[i].x = a[i + r.i1].x;
288             int ii = x.pfind(tmp.a[i].x);
289             if (ii < 0)
290                 tmp.a[i].y = x.a[-ii - 1].y * a[i + r.i1].y;
291             else
292                 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;
293         }
294         for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
295         {
296             int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
297             if (ii >= 0)
298             {
299                 tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
300                 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;
301             }
302             else
303             {
304                 kk++;
305                 glength --;
306                 tmp.length --;
307             }
308         }
309 
310         for (int i = 0; i < glength; i++)
311             for (int j = 0; j < glength - 1; j++)
312             if (tmp.a[j].x > tmp.a[j + 1].x)
313             {
314                 fun t = tmp.a[j];
315                 tmp.a[j] = tmp.a[j + 1];
316                 tmp.a[j + 1] = t;
317             }
318 
319         return tmp;
320     }
321 
322     F operator ^(F & x) const                                  //возведение функции слева от оператора в степень функции справа от оператора
323     {
324         int i1, e1, i2, e2, kk = 0;
325         double gfirstx, glastx, glength;
326 
327         if (((x.lastx < firstx) && (x.firstx < firstx)) || ((x.firstx < lastx) && (firstx < x.firstx)))
328         {
329             cout << "Nevozmozhno, prover'te oblasti opredelenia" << endl;
330             F fl(-1,0,0);
331             return fl;
332         }
333 
334         sf r = prepare(x);
335         F tmp(r.glength,r.gfirstx,r.glastx);
336 
337         for (int i = 0; i <= (r.e1 - r.i1); i++)
338         {
339             tmp.a[i].x = a[i + r.i1].x;
340             int ii = x.pfind(tmp.a[i].x);
341             if (ii < 0)
342                 tmp.a[i].y = pow(x.a[-ii - 1].y, a[i + r.i1].y);
343             else
344                 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);
345         }
346         for (int i = (r.e1 - r.i1 + 1); i <= (r.e2 - r.i2 + (r.e1 - r.i1) + 1) ; i++)
347         {
348             int ii = pfind(x.a[i - (r.e1 - r.i1 + 1) + r.i2].x);
349             if (ii >= 0)
350             {
351                 tmp.a[i - kk].x = x.a[i - (r.e1 - r.i1 + 1) + r.i2].x;
352                 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);
353             }
354             else
355             {
356                 kk++;
357                 glength --;
358                 tmp.length --;
359             }
360         }
361 
362         for (int i = 0; i < glength; i++)
363             for (int j = 0; j < glength - 1; j++)
364             if (tmp.a[j].x > tmp.a[j + 1].x)
365             {
366                 fun t = tmp.a[j];
367                 tmp.a[j] = tmp.a[j + 1];
368                 tmp.a[j + 1] = t;
369             }
370 
371         return tmp;
372     }
373 };
374 
375 int main()
376 {
377    /*
378     F f1(5,-2,1.5);
379     F f2(30,-10,0.5);
380     F f3, f4;
381     f1.FOut();
382     f2.FOut();
383     f3 = f1 + f2;
384     f3.FOut();
385     f4 = f1 * f2;
386     f4.FOut();
387     cout << " ________" << endl;
388 */
389     char vc, s[255], ce;
390     ifstream infile;
391     int n;
392     fun *a;
393     F f5,f6,f7,f8,f9;
394 
395     while(true)
396     {
397     start :
398         system("cls");
399         cout << "1 - Vvesti 1uu func"            << endl;
400         cout << "2 - Vvesti 2uu func"            << endl;
401         cout << "3 - Sloshit'"                   << endl;
402         cout << "4 - Umnozhit'"                  << endl;
403         cout << "5 - Vozvesti v stepen'"         << endl;
404         cout << "6 - Aproximirovat'"             << endl;
405         cout << "7 - Zapics' v file func"        << endl;
406         cout << "8 - Zapics' v file aprok fun"   << endl;
407         cout << "0 - Vihod"                      << endl;
408         cin  >> vc;
409         switch (vc)
410         {
411             case '0':
412                 return 0 ;
413             case '1':
414                 {
415                 system("cls");
416                 strcpy(s,"");
417                 delete []a;
418                 a = NULL;
419                 cout << "Vvedite imya fila" << endl;
420                 cin >> s;
421                 strcat(s, ".txt");
422                 infile.open(s);
423                 infile >> n;
424                 a = new fun [n];
425                 for(int i = 0; i < n; i ++)
426                     infile >> a[i].x >> a[i].y;
427                 f5.ad(a,n);
428                 f5.FOut();
429                 infile.close();
430                 cout << "Nazhmite \"b\" chotibi viti" << endl;
431                 cin >> ce;
432                 while (true)
433                 if (ce == 'b')
434                     goto start;
435                 }
436             case '2':
437                 {
438                 system("cls");
439                 strcpy(s,"");
440                 delete []a;
441                 a = NULL;
442                 cout << "Vvedite imya fila" << endl;
443                 cin >> s;
444                 strcat(s, ".txt");
445                 infile.open(s);
446                 infile >> n;
447                 a = new fun[n];
448                 for(int i = 0; i < n; i ++)
449                     infile >> a[i].x >> a[i].y;
450                 f6.ad(a,n);
451                 f6.FOut();
452                 infile.close();
453                 cout << "Nazhmite \"b\" chotibi viti" << endl;
454                 cin >> ce;
455                 while (true)
456                 if (ce == 'b')
457                     goto start;
458                 }
459             case '3':
460                 system("cls");
461                 f5.FOut();
462                 f6.FOut();
463                 f7 = f5 + f6;
464                 f7.FOut();
465                 cout << "Nazhmite \"b\" chotibi viti" << endl;
466                 cin >> ce;
467                 while (true)
468                 if (ce == 'b')
469                     goto start;
470             case '4':
471                 system("cls");
472                 f5.FOut();
473                 f6.FOut();
474                 f7 = f5 * f6;
475                 f7.FOut();
476                 cout << "Nazhmite \"b\" chotibi viti" << endl;
477                 cin >> ce;
478                 while (true)
479                 if (ce == 'b')
480                     goto start;
481             case '5':
482                 system("cls");
483                 f5.FOut();
484                 f6.FOut();
485                 f7 = f5 ^ f6;
486                 f7 = f5 ^ f6;
487                 f7.FOut();
488                 cout << "Nazhmite \"b\" chotibi viti" << endl;
489                 cin >> ce;
490                 while (true)
491                 if (ce == 'b')
492                     goto start;
493             case '6':
494             {
495                 system("cls");
496                 ap tmp = aproks(f7.geta(), f7.getlength());
497                 f8.addpar(tmp.k, tmp.b, f7.getlength(), f7.geta());
498                 f8.FOut();
499                 cout << "Nazhmite \"b\" chotibi viti" << endl;
500                 cin >> ce;
501                 while (true)
502                 if (ce == 'b')
503                     goto start;
504             }
505             case '7':
506             {
507                 system("cls");
508                 strcpy(s,"");
509                 cout << "Vvedite imya fila" << endl;
510                 cin >> s;
511                 strcat(s, ".txt");
512                 ofstream outfile(s);
513                 outfile << "x           y" << endl;
514                 for (int i = 0; i < f7.getlength(); i ++)
515                     outfile << f7.getelx(i) << "           " << f7.getely(i) << endl;
516 
517                 cout << "done" << endl;
518                 cout << "Nazhmite \"b\" chotibi viti" << endl;
519                 cin >> ce;
520                 while (true)
521                 if (ce == 'b')
522                     goto start;
523             }
524             case '8':
525                 system("cls");
526                 strcpy(s,"");
527                 cout << "Vvedite imya fila" << endl;
528                 cin >> s;
529                 strcat(s, ".txt");
530                 ofstream outfile(s);
531                 outfile << "x           y" << endl;
532                 for (int i = 0; i < f8.getlength(); i ++)
533                     outfile << f8.getelx(i) << "           " << f8.getely(i) << endl;
534                 cout << "done" << endl;
535                 cout << "Nazhmite \"b\" chotibi viti" << endl;
536                 cin >> ce;
537                 while (true)
538                 if (ce == 'b')
539                     goto start;
540         }
541     }
542     return 0;
543 }