Информатика: Функции — различия между версиями
Строка 3927: | Строка 3927: | ||
− | |||
'''[[Тимошенко Валентина]]''' | '''[[Тимошенко Валентина]]''' | ||
Строка 4276: | Строка 4275: | ||
} | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | '''[[Васильева Анастасия]]''' | ||
+ | |||
+ | '''Инструкция к программе''':сначала в папке с программой создаются два файла input1 и input2, в которых на первой строчке число точек в функции, а потом в два столбика значения х и у (функции должны быть с одинаковым шагом). Пользователь поочередно выбирает действия: 1 - нужно будет написать имя файла, откуда считывать значения для первой функции (х и у), 2 - для второй функции, 3 - сложение функций, пишем название файла, куда будут записываться значения, 4 - разность, 5 - умножение, 6 - интерполяция функции с шагом 0,5 , получившейся в результате сложения двух начальных,(можно сделать интерполяцию функций, которые получились в результате разности или умножения, но нужно будет в коде в case 6: newf3.Inter(0.5).output() поменять индекс функции и новый шаг), 7 - аппроксимация функции, получившейся в результате сложения двух начальных,(можно сделать аппроксимацию функций, которые получились в результате разности или умножения, но нужно будет в коде в case 7: newf3.Approxy().output() поменять индекс функции), 8 - выход. | ||
+ | |||
+ | '''Краткое описание алгоритма''': функции хранятся в программе как массив точек, заданных с определённым шагом по X на заданном отрезке. Вводить значения функции в программу можно считывая координаты точек из файла. Далее с любыми функциями можно производить следующие действия: сложение, вычитание, умножение, интерполяция и аппроксимация. При этом результат каждого из этих действий - новая функция. Результаты выводятся в файл. | ||
+ | Скачать программу можно по ссылке [http://tm.spbstu.ru/Файл:1.zip]. |
Версия 03:03, 18 января 2016
Описание программы: программа позволяет сложить, умножить, возвести одну в степень другой две таблично заданные функции, а также линейно аппроксимировать результат. Чтение и вывод происходит через файл.
Пояснения к алгоритму:
- Прочитанные из файла функции нужно отсортировать.
- Найти совместную область определения, то есть, найти множество пересечения областей определения функций, над которыми совершается операция.
- Создать третью функцию, со следующими свойствами : область определения состоит только из точек, принадлежащих совместной области определения, каждая точка области значений является результатом нужной операции над точкой области значений одной из функций и, либо интерполированной точкой по другой функции, либо, если есть возможность, точным значением из ее области значений.
Скачать можно тут.
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 }
Краткое описание алгоритма: Программа ищет совместную область определения для двух заданных пользователем функций. Для каждой из них вводится шаг и первое и последнее значения. После поиска совместной области программа интерполирует две функции и создает третью функцию, в которую сохраняются результаты работы программы, то есть сложение, вычитание, деление и умножение двух изначальных функций.
Инструкция к программе: Введите поочередно первый и последний элементы функций, а также их шаги. После этого введите число, соответствующее желаемому действию (соответствие указано в меню программы).
Посмотреть программу можно здесь
1 #include <iostream>
2 #include <fstream>
3 #include <cstring>
4 #include <stdlib.h>
5
6 using namespace std;
7
8 ofstream outfile;
9
10 struct approx //структура, необходимая для функции линейной интерполяции
11 {
12 double koefficientA, koefficientB;
13 };
14
15 struct dot //структура, содержащая в себе значения координат каждой точки
16 { //по обеим осям
17 double x, y;
18 };
19
20 struct polyana //структура, содержащая номера первого и последнего элемента каждой
21 { //функции и количество элементов каждой из них
22 int a1, a2, b1, b2, k1, k2;
23 };
24
25 struct trees //структура, содержащая номер элемента и логическое значение,
26 { // отвечающее за нужность или не нужность интерполяции
27 bool pol; //при равенстве или неравенстве энных элементов двух функций
28 int n;
29 };
30 //непосредственно функция линейной интерполяции
31 double pentagon (double x1, double x, double x2, double y1, double y2)
32 {
33 return (((x - x1)/(x2- x1))*(y2 - y1) + y1);
34 }
35
36 class stars //класс, позволяющий сохранять дискретные значения функции на
37 { //определенном интервале с определенным шагом
38 private:
39
40 double a; //первое значение функции
41 double b; //последнее значение функции
42 double step; //шаг
43 int length; //длина
44 int k; //счетчик количества элементов
45
46 public:
47
48 dot *massiv;
49 stars (int _k) //конструктор для создания объекта класса - структуры
50 { //с двумя полями по количеству элементов
51 massiv = new dot [_k];
52 k = _k;
53 }
54 stars () {}; //конструктор
55 stars (double _a, double _b, double _step) //конструктор для создания объекта класса через начальный
56 //и коненый элементы с определенным шагом
57 {
58 a = _a;
59 b = _b;
60 step = _step;
61
62 length = _b - _a + 1;
63 k = 0;
64
65 for (int i = _a ; i <= _b ; i += step) //подсчет количества элементов функции
66 {
67 k++;
68 }
69
70 massiv = new dot [k]; //задание функции
71 for (int i = 0 ; i < k ; i++)
72 {
73 massiv[i].x = _a + _step * i;
74 massiv[i].y = i * 5;
75 }
76 }
77
78 void outinfile () //вывод в файл значений функции
79 {
80 outfile.open ("meow", ios :: app);
81
82 outfile << "x" << " " << "y" << endl;
83 for (int i = 0 ; i < k ; i++)
84 {
85 outfile << massiv[i].x << " " << massiv[i].y << endl;
86 }
87 outfile << endl;
88 outfile.close();
89 }
90
91 void out () //вывод на экран значений функции
92 {
93 cout << "x" << " " << "y" << endl;
94 for (int i = 0 ; i < k ; i++)
95 {
96 cout << massiv[i].x << " " << massiv[i].y << endl;
97 }
98 cout << endl;
99 }
100
101 polyana prepare (stars &h) //подготовка совместной области определения для двух функций -
102 { //той части значений множества Х, на которой будут
103 trees del; //производиться вычисления
104 polyana tmp;
105 if (massiv[0].x > h.massiv[0].x) //поиск начала совместной области определения
106 {
107 del = h.love(massiv[0].x);
108 tmp.a2 = del.n + 1;
109 tmp.a1 = 0;
110 }
111 else
112 if (massiv[0].x < h.massiv[0].x)
113 {
114 del = love(h.massiv[0].x);
115 tmp.a2 = 0;
116 tmp.a1 = del.n + 1;
117 }
118 else
119 if (massiv[0].x == h.massiv[0].x)
120 {
121 tmp.a1 = 0;
122 tmp.a2 = 0;
123 };
124
125 if (massiv[k-1].x > h.massiv[k-1].x) //поиск конца совместной области определения
126 {
127 del = h.love(massiv[k-1].x);
128 tmp.b2 = k-1;
129 tmp.b1 = del.n;
130 }
131 else
132 if (massiv[k-1].x < h.massiv[k-1].x)
133 {
134 del = h.love(massiv[k-1].x);
135 tmp.b2 = del.n;
136 tmp.b1 = k-1;
137 }
138 else
139 if (massiv[k-1].x == h.massiv[k-1].x)
140 {
141 tmp.b2 = k-1;
142 tmp.b1 = k-1;
143 };
144
145 tmp.k1 = 0;
146 for (int i = tmp.a1 ; i <= tmp.b1 ; i ++) //подсчет количества элементов первой функции
147 {
148 tmp.k1++;
149 }
150 tmp.k2 = 0;
151 for (int i = tmp.a2 ; i <= tmp.b2 ; i ++) //подсчет количества элементов второй функции
152 {
153 tmp.k2++;
154 }
155 return tmp; //возвращает первые и последние значения обеих функций и
156 } //их количества элементов
157
158 //ПЕРЕГРУЗКА ОПЕРАТОРОВ
159
160 stars operator+ (stars & v) //сложение
161 {
162 polyana tmp = prepare(v);
163 int general = tmp.k1 + tmp.k2; //общее количество элементов обеих функций
164 stars F3(general); //создание объекта класса только по количеству элементов
165 for (int i = 0 ; i < tmp.k1 ; i++) //заполнение первой части окончательного результата
166 {
167 F3.massiv[i].x = massiv[i+tmp.a1].x;
168 trees tiger = v.love(massiv[i+tmp.a1].x);
169 if (tiger.pol == true) //если значения по У в одной точке не совпадают, то интерполировать
170 {
171 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x,
172 F3.massiv[i].x,
173 v.massiv[tiger.n + 1].x,
174 v.massiv[tiger.n].y,
175 v.massiv[tiger.n + 1].y )
176 + massiv[i+tmp.a1].y;
177 }
178 else //иначе, просто сложить значения
179 {
180 F3.massiv[i].y = v.massiv[tiger.n].y + massiv[i+tmp.a1].y;
181 }
182
183 }
184 {
185 for (int i = tmp.k1 ; i < (general) ; i++) //заполнение второй части окончательного результата
186 {
187 F3.massiv[i].x = v.massiv[i + tmp.a2 - tmp.k1].x;
188 trees tiger = love(v.massiv[i + tmp.a2 - tmp.k1].x);
189 if (tiger.pol == true)
190 {
191 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x,
192 F3.massiv[i].x,
193 v.massiv[tiger.n + 1].x,
194 v.massiv[tiger.n].y,
195 v.massiv[tiger.n + 1].y )
196 + v.massiv[i+tmp.a1 - tmp.k1].y;
197 }
198 else
199 F3.massiv[i].y = massiv[tiger.n].y + v.massiv[i+tmp.a2 - tmp.k1].y;
200 }
201
202 for (int i = 0; i < (general); i++) //сортировка
203 {
204 for (int j = 0; j < (general - 1); j ++)
205 {
206 dot temp;
207 if (F3.massiv[j].x > F3.massiv[j + 1].x)
208 {
209 temp = F3.massiv[j];
210 F3.massiv[j] = F3.massiv[j + 1];
211 F3.massiv[j + 1] = temp;
212 }
213 else //если элементы совпадают, то нужно выбросить один из них
214 if (F3.massiv[j].x == F3.massiv[j + 1].x)
215 {
216 int l = j;
217 while (l < general)
218 {
219 F3.massiv[l].x = F3.massiv[l + 1].x;
220 F3.massiv[l].y = F3.massiv[l + 1].y;
221 l++;
222 }
223 general--;
224 }
225 }
226 }
227
228
229 stars normalny (general); //создание элемента класса по длине
230 for (int i = 0; i < (general); i++)
231 {
232 normalny.massiv[i].x = F3.massiv[i].x;
233 normalny.massiv[i].y = F3.massiv[i].y;
234 }
235 a = normalny.massiv[0].x;
236 b = normalny.massiv[general].x;
237 return normalny;
238 }
239 };
240
241 stars operator* (stars & v) //умножение
242 {
243 polyana tmp = prepare(v);
244 int general = tmp.k1 + tmp.k2;
245 stars F3(tmp.k1 + tmp.k2);
246 for (int i = 0 ; i < tmp.k1 ; i++)
247 {
248 F3.massiv[i].x = massiv[i+tmp.a1].x;
249 trees tiger = v.love(massiv[i+tmp.a1].x);
250 if (tiger.pol == true)
251 {
252 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x, F3.massiv[i].x,
253 v.massiv[tiger.n + 1].x, v.massiv[tiger.n].y,
254 v.massiv[tiger.n + 1].y )* (massiv[i+tmp.a1].y);
255 }
256 else
257 {
258 F3.massiv[i].y = v.massiv[tiger.n].y * massiv[i+tmp.a1].y;
259 }
260
261 }
262 {
263 for (int i = tmp.k1 ; i < (general) ; i++)
264 {
265 F3.massiv[i].x = v.massiv[i+tmp.a2 - tmp.k1].x;
266 trees tiger = love(v.massiv[i+tmp.a2 - tmp.k1].x);
267 if (tiger.pol == true)
268 {
269 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x,
270 F3.massiv[i].x,
271 v.massiv[tiger.n + 1].x,
272 v.massiv[tiger.n].y,
273 v.massiv[tiger.n + 1].y )
274 + v.massiv[i+tmp.a1 - tmp.k1].y;
275 }
276 else
277 F3.massiv[i].y = massiv[tiger.n].y + v.massiv[i+tmp.a2 - tmp.k1].y;
278 }
279
280 for (int i= 0; i < (general); i++)
281 {
282 for (int j = 0; j < (general - 1); j ++)
283 {
284 dot temp;
285 if (F3.massiv[j].x > F3.massiv[j+1].x)
286 {
287 temp = F3.massiv[j];
288 F3.massiv[j] = F3.massiv[j+1];
289 F3.massiv[j+1] = temp;
290 }
291 else
292 if (F3.massiv[j].x == F3.massiv[j+1].x)
293 {
294 int l = j;
295 while (l < general)
296 {
297 F3.massiv[j].x = F3.massiv[j+1].x;
298 l++;
299 }
300 general--;
301 }
302 }
303 }
304
305 for (int i = 0 ; i < general ; i++)
306 {
307
308 cout <<F3.massiv[i].x<< ' ' << F3.massiv[i].y <<endl;
309 }
310
311
312 stars normalny(general);
313 for (int i = 0; i < (general); i++)
314 {
315 normalny.massiv[i].x = F3.massiv[i].x;
316 normalny.massiv[i].y = F3.massiv[i].y;
317 }
318 a = normalny.massiv[0].x;
319 b = normalny.massiv[general].x;
320 return normalny;
321 }
322 };
323
324 stars operator- (stars & v) //вычитание
325 {
326 polyana tmp = prepare(v);
327 int general = tmp.k1 + tmp.k2;
328 stars F3(tmp.k1 + tmp.k2);
329 for (int i = 0 ; i < tmp.k1 ; i++)
330 {
331 F3.massiv[i].x = massiv[i+tmp.a1].x;
332 trees tiger = v.love(massiv[i+tmp.a1].x);
333 if (tiger.pol == true)
334 {
335 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x, F3.massiv[i].x,
336 v.massiv[tiger.n + 1].x, v.massiv[tiger.n].y,
337 v.massiv[tiger.n + 1].y )- massiv[i+tmp.a1].y;
338 }
339 else
340 {
341 F3.massiv[i].y = v.massiv[tiger.n].y - massiv[i+tmp.a1].y;
342 }
343
344 }
345 {
346 for (int i = tmp.k1 ; i < (general) ; i++)
347 {
348 F3.massiv[i].x = v.massiv[i+tmp.a2 - tmp.k1].x;
349 trees tiger = love(v.massiv[i+tmp.a2 - tmp.k1].x);
350 if (tiger.pol == true)
351 {
352 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x,
353 F3.massiv[i].x,
354 v.massiv[tiger.n + 1].x,
355 v.massiv[tiger.n].y,
356 v.massiv[tiger.n + 1].y )
357 + v.massiv[i+tmp.a1 - tmp.k1].y;
358 }
359 else
360 F3.massiv[i].y = massiv[tiger.n].y + v.massiv[i+tmp.a2 - tmp.k1].y;
361 }
362
363 for (int i= 0; i < (general); i++)
364 {
365 for (int j = 0; j < (general - 1); j ++)
366 {
367 dot temp;
368 if (F3.massiv[j].x > F3.massiv[j+1].x)
369 {
370 temp = F3.massiv[j];
371 F3.massiv[j] = F3.massiv[j+1];
372 F3.massiv[j+1] = temp;
373 }
374 else
375 if (F3.massiv[j].x == F3.massiv[j+1].x)
376 {
377 int l = j;
378 while (l < general)
379 {
380 F3.massiv[j].x = F3.massiv[j+1].x;
381 l++;
382 }
383 general--;
384 }
385 }
386 }
387
388 for (int i = 0 ; i < general ; i++)
389 {
390
391 cout <<F3.massiv[i].x<< ' ' << F3.massiv[i].y <<endl;
392 }
393
394
395 stars normalny(general);
396 for (int i = 0; i < (general); i++)
397 {
398 normalny.massiv[i].x = F3.massiv[i].x;
399 normalny.massiv[i].y = F3.massiv[i].y;
400 }
401 a = normalny.massiv[0].x;
402 b = normalny.massiv[general].x;
403 return normalny;
404 }
405 };
406
407 stars operator/ (stars & v) //деление
408 {
409 polyana tmp = prepare(v);
410 int general = tmp.k1 + tmp.k2;
411 stars F3(tmp.k1 + tmp.k2);
412 for (int i = 0 ; i < tmp.k1 ; i++)
413 {
414 F3.massiv[i].x = massiv[i+tmp.a1].x;
415 trees tiger = v.love(massiv[i+tmp.a1].x);
416 if (tiger.pol == true)
417 {
418 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x, F3.massiv[i].x,
419 v.massiv[tiger.n + 1].x, v.massiv[tiger.n].y,
420 v.massiv[tiger.n + 1].y )/ (massiv[i+tmp.a1].y);
421 }
422 else
423 {
424 F3.massiv[i].y = (v.massiv[tiger.n].y) / (massiv[i+tmp.a1].y);
425 }
426
427 }
428 {
429 for (int i = tmp.k1 ; i < (general) ; i++)
430 {
431 F3.massiv[i].x = v.massiv[i+tmp.a2 - tmp.k1].x;
432 trees tiger = love(v.massiv[i+tmp.a2 - tmp.k1].x);
433 if (tiger.pol == true)
434 {
435 F3.massiv[i].y = pentagon (v.massiv[tiger.n].x,
436 F3.massiv[i].x,
437 v.massiv[tiger.n + 1].x,
438 v.massiv[tiger.n].y,
439 v.massiv[tiger.n + 1].y )
440 + v.massiv[i+tmp.a1 - tmp.k1].y;
441 }
442 else
443 F3.massiv[i].y = massiv[tiger.n].y + v.massiv[i+tmp.a2 - tmp.k1].y;
444 }
445
446 for (int i= 0; i < (general); i++)
447 {
448 for (int j = 0; j < (general - 1); j ++)
449 {
450 dot temp;
451 if (F3.massiv[j].x > F3.massiv[j+1].x)
452 {
453 temp = F3.massiv[j];
454 F3.massiv[j] = F3.massiv[j+1];
455 F3.massiv[j+1] = temp;
456 }
457 else
458 if (F3.massiv[j].x == F3.massiv[j+1].x)
459 {
460 int l = j;
461 while (l < general)
462 {
463 F3.massiv[j].x = F3.massiv[j+1].x;
464 l++;
465 }
466 general--;
467 }
468 }
469 }
470
471 for (int i = 0 ; i < general ; i++)
472 {
473
474 cout <<F3.massiv[i].x<< ' ' << F3.massiv[i].y <<endl;
475 }
476
477
478 stars normalny(general);
479 for (int i = 0; i < (general); i++)
480 {
481 normalny.massiv[i].x = F3.massiv[i].x;
482 normalny.massiv[i].y = F3.massiv[i].y;
483 }
484 a = normalny.massiv[0].x;
485 b = normalny.massiv[general].x;
486 return normalny;
487 }
488 };
489
490 trees love (double a) //
491 {
492 trees privet;
493 for (int i = 0; i < k; i++ )
494 if ((massiv[i].x < a)&& (a < massiv[i+1].x))
495 {
496 privet.n = i;
497 privet.pol = true;
498 return privet;
499 }
500 else
501 if (massiv[i].x == a)
502 {
503 privet.n = i;
504 privet.pol = false;
505 return privet;
506 }
507 else
508 if (massiv[i+1].x == a)
509 {
510 privet.n = i+1;
511 privet.pol = false;
512 return privet;
513 }
514 }
515
516
517 approx approximate () //функция аппроксимации
518 {
519 approx hey;
520 stars mattafix (double a, double b, double step, int k, int length);
521 double sigmaX = 0;
522 double sigmaY = 0;
523 double sigmaXY = 0;
524 double sigmaXsqrt = 0;
525 for (int i = 0; i < length; i++)
526 {
527 sigmaX += a + step * i;
528 sigmaY += b + i * 5;
529 sigmaXY += (a + step * i)*(b + i * 5);
530 sigmaXsqrt += (a + step * i)*(a + step * i);
531 }
532 hey.koefficientA = ((k * (sigmaXY) - (sigmaX*sigmaY))/(k*sigmaXsqrt - (sigmaX * sigmaX)));
533 hey.koefficientB = ((sigmaY - hey.koefficientA*sigmaX)/k);
534 return hey;
535
536
537 }
538 };
539
540 int main()
541 {
542 int tyu;
543 stars function3;
544 int firstnumber1;
545 int firstnumber2;
546 int lastnumber1;
547 int lastnumber2;
548 int step1;
549 int step2;
550 while (true)
551 {
552
553 cout << "Input 0 - vvedite parametry pervoy funkcii"<< endl;
554 cout << "Input 1 - vvedite parametry vtoroy funkcii"<< endl;
555 cout << "Input 2 - slozhenie"<< endl;
556 cout << "Input 3 - umnozhenie"<< endl;
557 cout << "Input 4 - delenie"<< endl;
558 cout << "Input 5 - vychitanie"<< endl;
559 cout << "Input 6 - aproximate"<< endl;
560 cin >> tyu ;
561
562 switch (tyu)
563 {
564 case 0:
565 { cout << "Vvedite pervy x" << endl;
566 cin >> firstnumber1;
567 cout << "Vvedite posledniy x" << endl;
568 cin >> lastnumber1;
569 cout << "Vvedite shag" << endl;
570 cin >> step1;
571 break;
572 }
573 case 1:
574 {
575 cout << "Vvedite pervy x" << endl;
576 cin >> firstnumber2;
577 cout << "Vvedite posledniy x" << endl;
578 cin >> lastnumber2;
579 cout << "Vvedite shag" << endl;
580 cin >> step2;
581 break;
582 }
583 case 2:
584 {
585 stars function1 (firstnumber1, lastnumber1, step1);
586 function1.out();
587 function1.outinfile ();
588
589 stars function2 (firstnumber2, lastnumber2, step2);
590 function2.out();
591 function2.outinfile ();
592
593 function3 = function1 + function2;
594 function3.out();
595 function3.outinfile ();
596 break;
597 }
598 case 3:
599 {
600 stars function1 (firstnumber1, lastnumber1, step1);
601 function1.out();
602 function1.outinfile ();
603
604 stars function2 (firstnumber2, lastnumber2, step2);
605 function2.out();
606 function2.outinfile ();
607
608 function3 = function1 * function2;
609 function3.out();
610 function3.outinfile ();
611 break;
612 }
613 case 4:
614 {
615 stars function1 (firstnumber1, lastnumber1, step1);
616 function1.out();
617 function1.outinfile ();
618
619 stars function2 (firstnumber2, lastnumber2, step2);
620 function2.out();
621 function2.outinfile ();
622
623 function3 = function1 / function2;
624 function3.out();
625 function3.outinfile ();
626 break;
627 }
628 case 5:
629 {
630
631 stars function1 (firstnumber1, lastnumber1, step1);
632 function1.out();
633 function1.outinfile ();
634
635 stars function2 (firstnumber2, lastnumber2, step2);
636 function2.out();
637 function2.outinfile ();
638
639 function3 = function1 - function2;
640 function3.out();
641 function3.outinfile ();
642 break;
643 }
644 case 6:
645 {
646 approx you;
647 function3.approximate();
648 outfile.open ("meow", ios :: app);
649 outfile << "Y = "<< you.koefficientA <<"* x + "<<you.koefficientB << endl;
650 outfile << endl;
651 outfile.close();
652
653
654 }
655 }
656 }
657 };
Краткое описание алгоритма : Программа создаёт и хранит значения двух функций с одинаковом шагом и заданных на одинаковом интервале.Методы позволяют сложить эти две функции,интерполировать одну из них по заданному шагу или апроксимировать,методом наименьших квадратов.
Инструкция к программе: Начальная координата и шаг,для задания координат функций,передаются при вызове методов,создающих функции.Начальный шаг,шаг интерполяции,а так же количество выводимых координат заданы глобально.Поэтому просто запускайте программу, при желании поменяйте заданные величины.
Cкачать программу можно здесь
1 #include <iostream>
2
3 using namespace std;
4
5 #define N 5//количество точек
6
7 const double l1 = 5;//задаём начальный шаг функций
8 const double l2 = 0.7;//шаг для интерполяции
9
10 class Func
11 {//класс,хранящий функцию,содержащий методы:печать,перегрузка,интерполяция,апроксимация
12
13 public:
14 Func(int size) : size_(size), ax(new double[size]), by(new double[size])//создаём два массива,заполняем нулями
15 {
16 for (int i = 0; i< size_; i++)
17 {
18 ax[i] = 0;
19 by[i] = 0; //все элементы обоих массивов обнуляются
20 }
21 }
22
23 void print()//вывод на экран
24 {
25 cout << "x: ";
26 for (int i = 0; i < size_; i++)
27 cout << ax[i] << " ";
28 cout << endl << "y: ";
29 for (int i = 0; i < size_; i++)
30 cout << by[i] << " ";
31 cout << endl;
32 }
33
34 Func &operator+(Func &f2)//функция перегрузки:cложение функций
35 {
36 Func *result = new Func(size_);//создаём результирующую функцию,равную сумме двух f2 и this
37 for (int i = 0; i < size_; i++)
38 {
39 result->ax[i] = this->ax[i];//суммируем координаты X
40 result->by[i] = f2.by[i] + this->by[i];//суммируем координаты Y
41 }
42 cout << "Sum f(x)=f1+f2:" << endl;//выводим на экран сумму функций
43 result->print();
44 return *result;
45 }
46
47 void Int(double L) //метод Интерполяции
48 {
49 int M = (this->ax[this->size_ - 1] - this->ax[0]) / L + 1; //M- количество элементов массива с координатами интерполирующей функции;
50 Func result = Func(M);//cоздаём функцию,в кторой будет храниться результат интерполяции
51 cout << "M =" << M << endl;//выводим M для проверки
52 cout << "Interpolation: " << endl;
53 int t;
54 for (int i = 1; i < M; i++)
55 {
56 result.ax[0] = this->ax[0];
57 result.ax[i] = result.ax[i - 1] + L;//интерполируем Х,прибавляя шаг к каждому предыдущему элементу
58 t = (result.ax[i - 1] - result.ax[0]) / l1;//считаем номер элемента,"левого" от искомого
59
60 //интерполируем Y по формуле
61 result.by[i] = this->by[t] + ((result.ax[i] - this->ax[t]) / (this->ax[t + 1] - this->ax[t]))*(this->by[t + 1] - this->by[t]);
62
63 }
64
65 result.print();//выводим результат
66 }
67
68 void aprox()//Апроксимация
69 {
70 double a=0;
71 for(int i=0;i<size_;i++)//считаем сумму x
72 a=this->ax[i]+a;
73
74
75 double b=0;
76 for(int i=0;i<size_;i++)//считаем сумму y
77 b=this->by[i]+b;
78
79
80 double c=0;
81 for(int i=0;i<size_;i++)//считаем сумму квадратов x
82 c=(this->ax[i])*(this->ax[i])+c;
83
84
85 double d=0;
86 for(int i=0;i<size_;i++)//считаем сумму xy
87 d=(this->ax[i])*(this->by[i])+d;
88
89
90 //затем решаем систему для у=kx+m
91 //(1)c*k+a*m=d
92 //(2)a*k+size_*m=b;
93 //k=(d-am)/с
94 //подставим в (2)
95 double m;
96 m=(b*c-a*d)/(c*size_-a*a);
97 double k;
98 k=(d-a*m)/c;
99 cout<<"aproximacia :: ";
100 cout<<"y="<<k<<"x+"<<m<<endl;
101
102 }
103
104
105 double *ax;
106 double *by;
107
108 private:
109 int size_;//размер массива
110 };
111
112
113
114
115 class Cord//класс,создающий и хранящий значение функций
116 {
117 public:
118 Cord(double x0, double s) :x0(x0), s(s)//x0-начальная координата;s-шаг
119 {
120 }
121
122 void Fyx1(Func func)//метод,считающий координаты нашей функции y=x
123 {
124 int i;
125 func.ax[0] = x0;
126 for (i = 1; i < N; i++)//считаются иксы
127 {
128 func.ax[i] = x0 + s;
129 x0 = func.ax[i];
130 }
131 for (i = 0; i<N; i++)
132 func.by[i] = func.ax[i];//считаем координаты у
133 cout << "f1 :" << endl;
134 func.print();
135 cout << endl;
136 }
137
138 void Fyx2(Func func)//метод,считающий координаты нашей функции y=x+1
139 {
140 int i;
141 func.ax[0] = x0;
142 for (i = 1; i<N; i++)//считаем иксы
143 {
144 func.ax[i] = x0 + s;
145 x0 = func.ax[i];
146 }
147 for (i = 0; i<N; i++)
148 func.by[i] = func.ax[i] + 1;//считаем игрики
149 cout << "f2 :" << endl;
150 func.print();
151 cout << endl;
152 }
153
154 private:
155 double x0;//начальная координата
156 double s;//шаг
157 };
158
159 int main()
160 {
161 Func f1(N);//создание функции f1
162 Func f2(N);//создание f2
163 Cord s1(0, l1);//cоздаём объект s1
164 Cord s2(0, l1);//cоздаём объект s2
165 s1.Fyx1(f1);//задаём координаты 1ой функции
166 s2.Fyx2(f2);//задаём координаты 2ой функции
167
168 //сложение функций:
169
170 Func f3 = f2 + f1;//есть тоже ,что и Func f3 = f2.operator+(f1);
171
172 f1.Int(l2);//Интерполируем f1 с новым шагом l2
173 f1.aprox();//Апроксимируем f1
174
175 getchar();
176 return 0;
177 }
Описание программы: программа позволяет сложить, умножить, возвести одну в степень другой две таблично заданные функции, а также линейно аппроксимировать результат. Чтение и вывод происходит через файл.
Пояснения к алгоритму: Программа создаёт и хранит значения двух функций с одинаковом шагом и заданных на одинаковом интервале. Методы позволяют сложить эти две функции,интерполировать одну из них по заданному шагу или апроксимировать методом наименьших квадратов. Данные берутся из файла. При считывании с файла сначала указывается отрезок, потом величина, а потом дискретные значения.
Скачать можно тут.
Сюрис Александр
Задаются две функции с разными шагами и начальными и конечными значениями. Аппроксимирует одну функцию по шагу другой и складывает/умножает/вычитает/делит их
Скачать можно тут.
1 #include <iostream>
2 #include <vector>
3 #include<math.h>
4
5 using namespace std;
6 class f{
7 private:
8 double st, en, d; //начало, конец, дельта
9 vector<double> v;//вектор, содержащий y
10 public:
11 f(double _st, double _en, double _d, vector<double> _v){
12 st=_st;
13 en=_en;
14 d=_d;
15 for(int i=0;i<_v.size();i++) //копируем массив, который вводим в консоль
16 v.push_back(_v[i]);
17 //return *this;
18 }
19 f(){};
20 f aprox(double _st, double _en, double _d){ //метод интерполяции, поиск коэфф a и b для y=ax+b
21 double sum_x=0, sum_y=0, sum_2x=0,sum_xy=0,a,b;
22 for(int i=0; i<=(en-st)/d; i++)
23 sum_x=sum_x+st+i*d;
24 for(int i=0; i<=(en-st)/d; i++)
25 sum_y=sum_y+v[i];
26 for(int i=0; i<=(en-st)/d; i++)
27 sum_2x=sum_2x+pow(st+i*d,2);
28 for (int i=0; i<=(en-st)/d; i++)
29 sum_xy=sum_xy+v[i]*(st+i*d);
30 a=(((en-st)/d+1)*sum_xy-sum_x*sum_y)/(((en-st)/d+1)*sum_2x-sum_x*sum_x);
31 b=(sum_y-a*sum_x)/(((en-st)/d+1));
32
33 vector<double> v1;//вектор, содержащий проинтерполированную функцию
34 for(int i=0; i<=(en-st)/d; i++)
35 v1.push_back(a*(st+i*d)+b);//добавление значений проинтерполированной ф-ции с шагом другой функции
36 return f(_st,_en,_d,v1);
37
38 }
39
40 f operator +(f x){//оператор сложения
41 double _en,_st,_d;
42 _en=min(en,x.en); //поиск области пересечения
43 _st=max(st,x.st);
44 if (_en>_st){//проверяем, пересекаются ли функции
45 vector<double> _v;
46 f y;
47 if(x.st<st){ //сравниваем начала двух отрезков, для того, чтобы выбрать, какую функцию апроксимировать
48 vector<double> _v;
49 y=x.aprox(_st, _en, d);
50 for (int i=0; i<=(_en-_st)/d; i++)
51 _v.push_back(y.v[i]+v[i]); //вектор с суммой функций
52 return f(_st,_en,d,_v);
53 }
54 else{
55 vector<double> _v;
56 y=this->aprox(_st, _en, x.d); //this-> функция, в которой мы работаем
57 for (int i=0; i<=(_en-_st)/x.d; i++)
58 _v.push_back(y.v[i]+x.v[i]);
59 return f(_st,_en,x.d,_v);
60 }
61 }
62 }
63
64 f prot(){ //поиск противоположной функции
65 for (int i=0; i<=(en-st)/d; i++)
66 v[i]=(-1)*v[i];
67 return *this;
68 }
69
70 f operator - (f x){ //разность функций
71 return(*this + x.prot());
72 }
73
74 f operator *(f x){//оператор умножения
75 double _en,_st,_d;
76 _en=min(en,x.en); //поиск области пересечения
77 _st=max(st,x.st);
78 if (_en>_st){//проверяем, пересекаются ли функции
79 vector<double> _v;
80 f y;
81 if(x.st<st){ //сравниваем начала двух отрезков, для того, чтобы выбрать, какую функцию апроксимировать
82 vector<double> _v;
83 y=x.aprox(_st, _en, d);
84 for (int i=0; i<=(_en-_st)/d; i++)
85 _v.push_back(y.v[i]*v[i]); //вектор с суммой функций
86 return f(_st,_en,d,_v);
87 }
88 else{
89 vector<double> _v;
90 y=this->aprox(_st, _en, x.d); //this-> функция, в которой мы работаем
91 for (int i=0; i<=(_en-_st)/x.d; i++)
92 _v.push_back(y.v[i]*x.v[i]);
93 return f(_st,_en,x.d,_v);
94 }
95 }
96 }
97
98 f obr(){
99 for (int i=0; i<=(en-st)/d; i++)
100 v[i]=1/v[i];
101 return *this;
102 }
103
104 f operator /(f x){
105 return(*this*x.obr());
106 }
107
108 void vivod(){ //вывод
109 for(int i=0; i<v.size(); i++)
110 cout<<v[i]<<" ";
111
112 }
113 };
114 int main(){
115 setlocale(LC_ALL, "Russian");
116 double a,b,a1,b1,d,d1,t;
117 int o;
118 cout << "Введите начала и конец отрезка и дельту: ";
119 cin>>a>>b>>d;
120 int amount=(b-a)/d+1,amount2;
121 vector<double>x;
122 cout << "Введите " << amount << " значений функции на данном интервале:";
123 for (int i=0; i<amount; i++)
124 {
125 cin>>t;
126 x.push_back(t);
127 }
128
129 cout << "Проделаем ровно то же самое для 2 функции ";
130 cout << "Введите начала и конец отрезка и дельту: ";
131 cin >> a1 >> b1 >> d1;
132
133 amount2=(b1-a1)/d1+1;
134 vector<double>y;
135 cout << "Введите " << amount2 << " значений функции на данном интервале:";
136 for (int i=0; i<amount2; i++)
137 {
138 cin>>t;
139 y.push_back(t);
140 }
141 f g(a,b,d,x);
142 f h(a1,b1,d1,y);
143
144 cout<<"Выберете дейстивя с функциями: +, -, *, \ " << endl;
145 cout<<"Введите число, соответсвующее порядковому номеру операции(1-4) - ";
146 cin>>o;
147 if(o==1){ //по невыясненным причинам одновременно написанные слева идущие if -ы не работают,
148 cout<<"Сумма:"; //но если заккоментить их и менять знак + в скобке на другие, то все работает
149 (g+h).vivod();
150
151 }
152
153 if(o==2){
154 cout<<"Разность:"
155 (g-h).vivod();
156
157 }
158
159 if(o==3){
160 cout<<"Произведение:"
161 (g*h).vivod();
162
163
164 }
165
166 if(o==3){
167 cout<<"Отношение:"
168 (g/h).vivod();
169 }
170
171
172 }
Инструкция к программе: пользователь должен ввести начало, конец и шаг. Создается две функции. Затем на экране появляется один из знаков арифметических действий. Пользователь выбирает один из знаков. Создается третья функция. Пользователь вводит второй шаг. Функция интерполируется по этому новому шагу, а затем аппроксимируется. Краткое описание алгоритма : в классе создается две функции(с помощью массивов). Так же в классе есть такие методы: перегрузка арифм операций, интерполяция, аппроксимация, вывод массивов на экран и их сохранение в файл. Сначала создается два массива для функций. Затем с помощью перегрузки эти два массива складываются/умножаются/делятся/вычитаются и записываются опять в этот массив. В методе перегрузки сразу вызывается интерполяция и аппроксимация. Программа
1 #include <iostream>
2 #include <fstream>
3 #include "math.h"
4 using namespace std;
5 class func
6 {
7 private:
8 double *mass1, *mass, *masss ;
9 double AmountDouble, Begin, End, Step, Step2;
10 public:
11 int AmountInt;
12 func ( double _Begin, double _End, double _Step ):Begin(_Begin), End(_End), Step(_Step)
13 {
14 AmountDouble=((End-Begin)/Step)+1;///количество точек с данным шагом
15 AmountInt=static_cast<int>(AmountDouble);///так как количество это целое число, то округляем
16
17 }
18
19 void massiv1() ///создание первой функции х^3
20 {
21 mass=new double[AmountInt];
22 for (int l=0; l<AmountInt; l++)
23 {
24 mass[l] =pow((l*Step+Begin),3);
25 }
26 cout << "y=x^3 \n";
27 }
28 void massiv2() ///создание второй функции sin(x)
29 {
30 mass=new double[AmountInt];
31 for (int l=0; l<AmountInt; l++)
32 {
33 mass[l] =sin(l*Step+Begin);
34 }
35 cout << "y=sin(x) \n";
36 }
37
38 void interpolation(double __Begin, double __End, double __Step)
39 {
40
41 double NewAmount=((__End-__Begin)/__Step) + 1;///количество точек для нового шага
42 int NewAmountInt=static_cast<int>(NewAmount);
43 for (int i=0; i<NewAmountInt; i++)///i-это точки функции с новыми шагами
44 {
45 mass1 = new double[NewAmountInt];
46 double x = i*__Step+__Begin;///значения х в новых точках
47 double x0=(static_cast<int>((x-__Begin)/Step)) * Step+__Begin;///значение х в точке интерполяции
48 ///стоящей ДО новой точки
49 double x1=x0+Step;///точка интерполяции ПОСЛЕ новой точки, т.е к предыдущей прибавляем СТАРЫЙ шаг
50 int i0=(static_cast<int>((x-__Begin)/Step));///это нужно для массива, значение массива в i0 соответстует значению функции в x0
51 int i1=i0+1;
52 mass1[i]=(((x - x0 )*(mass[i1] - mass[i0]))/( x1-x0)) + mass[i0];
53 cout << "y("<<i<< ") = " << mass1[i] <<endl<<endl; ///вывод интерполяции на экран
54 std::ofstream fout("Interpol.txt",ios::app);///сохранение в файл
55 fout<<i<<" "<<mass1[i]<<" \n";
56 fout.close();
57 }
58 AmountInt=NewAmountInt;
59 delete[] mass;
60 mass=mass1;
61 cout<<"end of interpol";
62 }
63
64 void approximation(double __Begin, double __End, double __Step)
65
66 {
67 double SumXMass=0;///это сумма умножений x на значение функции в этом x для всех значений
68 double SumX=0;///сумма всех значений x
69 double SumMass=0;///сумма всех значений функции в точках x
70 double SumXX=0;///сумма всех квадратов значений x
71 mass1 = new double[AmountInt];
72 double x;
73 for (int i=0; i<AmountInt; i++)
74 {
75 x=i*__Step+__Begin;///такие значения принимает x в точках по порядку i
76 SumXMass=SumXMass+x*mass[i];
77 SumX=SumX+x;
78 SumMass=SumMass+mass[i];
79 SumXX=SumXX+x*x;
80
81 }
82 double a=(SumXMass*AmountInt-SumX*SumMass)/(AmountInt*SumXX-SumX*SumX);
83 double b=(SumMass-a*SumX)/AmountInt;
84 if (b>0)
85 cout<<"approximation "<<a<<"*x+"<<b<<endl;
86 else if (b<0)
87 cout<<"approximation "<<a<<"*x"<<b<<endl;
88
89 for (int i=0; i<AmountInt; i++)
90 {
91 mass1[i] = a*(i*__Step+__Begin)+b;///такие значения принимает апроксимация
92 }
93 delete[] mass;
94 mass=mass1;
95 output();///вывод на экран
96 SaveFile("approximation.txt");///сохранение в файл
97 cout<<"end of appox";
98
99 }
100
101 func operator+( func f)///перегрузка оператора +
102 {
103 func newmass(Begin, End, Step);
104 masss=new double[AmountInt];///новая функция равная сумме данныйх функций
105 for (int i=0; i<AmountInt; i++)
106 {
107 masss[i] = mass[i] + f.mass[i];
108 }
109 delete [] mass;
110 mass=masss;
111 output();///вывод на экран резултата
112 SaveFile("f3.txt");///сохранение в файл
113 cout<<"enter new step";
114 cin>>Step2;
115 cout<<"interpolation: ";
116 interpolation(Begin,End,Step2);///интерполяция
117 cout<<" approximation: ";
118 approximation(Begin,End,Step2);///аппроксимация
119 return newmass;
120
121 }
122
123 func operator-( func f)
124 {
125 func newmass(Begin, End, Step);
126 masss=new double[AmountInt];
127 for (int i=0; i<AmountInt; i++)
128 {
129 masss[i] = mass[i] - f.mass[i];
130 }
131 delete [] mass;
132 mass = masss;
133 output();
134 SaveFile("f3.txt");
135 cout<<"enter new step";
136 cin>>Step2;
137 cout<<"interpolation: ";
138 interpolation(Begin,End,Step2);
139 cout<<" approximation: ";
140 approximation(Begin,End,Step2);
141 return newmass;
142 }
143 func operator/( func f)
144 {
145 func newmass(Begin, End, Step);
146 masss=new double[AmountInt];
147 for (int i=0; i<AmountInt; i++)
148 {
149 masss[i] = mass[i] / f.mass[i];
150 }
151 cout << " division: \n ";
152 delete [] mass;
153 mass = masss;
154 output();
155 SaveFile("f3.txt");
156 cout<<"enter new step";
157 cin>>Step2;
158 cout<<"interpolation: ";
159 interpolation(Begin,End,Step2);
160 cout<<" approximation: ";
161 approximation(Begin,End,Step2);
162 return newmass;
163 }
164 func operator*( func f)
165 {
166 func newmass(Begin, End, Step);
167 masss=new double[AmountInt];
168 for (int i=0; i<AmountInt; i++)
169 {
170 masss[i] = mass[i] * f.mass[i];
171 }
172 cout << " multiply: \n ";
173 delete [] mass;
174 mass = masss;
175 output();
176 SaveFile("f3.txt");
177 cout<<"enter new step";
178 cin>>Step2;
179 cout<<"interpolation: ";
180 interpolation(Begin,End,Step2);
181 cout<<" approximation: ";
182 approximation(Begin,End,Step2);
183 return newmass;
184 }
185
186
187 void output()///вывод функции на экран
188 {
189 for (int i=0; i<AmountInt; i++)
190 {
191 cout << "y("<<i<< ") = " << mass[i] <<endl;
192
193 }
194 }
195
196
197 void SaveFile(char filename[])///сохранение функции в файл
198 {
199 std::ofstream fout(filename);
200 for (int l=0; l<AmountInt; l++)
201 {
202 fout<<l<<" "<<mass[l]<<" \n";
203 }
204
205 fout.close();
206 }
207 };
208
209
210
211 int main()
212 {
213
214 double Begin1, End1, Step1, Step2;
215 cout<<" enter the beginning of the function ";
216 cin>>Begin1;
217 cout<<"\n enter the end of the function ";
218 cin>>End1;
219 cout<<"\n enter the step of the 1st function ";
220 cin>>Step1;
221
222 func f1(Begin1,End1,Step1);///создание первой функции
223 f1.massiv1();
224 f1.output();
225 cout<<"\n ";
226 f1.SaveFile("f1.txt");
227
228 func f2(Begin1,End1,Step1);///создание второй функции
229 f2.massiv2();
230 f2.output();
231 cout<<"\n ";
232 f2.SaveFile("f2.txt");
233 cout<<"\n";
234
235 func f3(Begin1,End1,Step1);
236
237 cout<<" \n \n choose 1 - sum , 2 - subtract, 3 - division, 4 - multiply \n";///выбор операции
238 int z;
239 cin>>z;
240 switch (z)
241 {
242 case 1:
243 {
244 f3=f1+f2;///сумма функций
245 break;
246 }
247 case 2:
248 {
249 f3=f1-f2;
250 break;
251 }
252 case 3:
253 {
254 f3=f1/f2;
255 break;
256 }
257 case 4:
258 {
259 f3=f1*f2;
260 break;
261 }
262
263 default :
264 {
265 cout<<"NOOOOO";
266 break;
267 }
268 };
269 return 0;
270 }
Инструкция к программе: пользователь вводит начало и конец отрезка и шаг для функций, после чего создается две функции. Затем пользователь выбирает одну из арифметических операций, которую он хочет применить к этим функциям. Создается третья функция. После пользователь вводит второй шаг для интерполяции. Третья функция интерполируется по новому шагу, а затем аппроксимируется.
Краткое описание алгоритма: в классе при помощи массива создаются две функции, с которыми потом работает программа. Эти функции перегружаются операторами арифметических операций, где затем полученная новая функция интерполируется и аппроксимируется.
Скачать программу можно по ссылке [1].
1 #include <iostream>
2 #include <locale.h>
3 #include <math.h>
4 #include <fstream>
5 #include<iomanip>
6
7 using namespace std;
8
9 class functya ///создаем класс функции
10 {
11
12 private: ///объявляем тип переменных в привате
13 double *mass, *mass1, *mass2; ///*mass, *mass1, *mass2 -определение двумерного массива
14 double start, ending, step, step2, amountdouble; ///start-начало, ending-конец, step-шаг, amountdouble-количество точек (типа double)
15
16 public: ///объявляем тип переменных в паблике
17 int amount; ///amoun-количество точек (типа int)
18
19 functya (double _start, double _ending, double _step):start(_start),ending(_ending),step(_step) ///создаем конструктор функции с объявлением переменных
20 {
21
22 amountdouble=((ending-start)/step)+1; ///подсчитываем количество точек с заданым шагом
23 amount=static_cast<int>(amountdouble); ///преобразуем количество из типа double к типу int
24
25 }
26
27 void massiv1 () ///создаем функцию массива
28 {
29
30 mass=new double[amount]; ///создаем двумерный массив
31 for (int l=0; l<amount; l++) ///создаем цикл от нуля до amount-количества точек
32 {
33 mass[l]= pow((l*step+start),3); ///при помощи массива задаем функцию с которой будем работать
34 }
35 cout<< "\n";
36 }
37
38 void massiv2 () ///создаем функцию массива
39 {
40
41 mass=new double[amount]; ///создаем двумерный массив
42 for (int l=0; l<amount; l++) ///создаем цикл от нуля до amount-количества точек
43 {
44 mass[l]= pow((l*step+start),2); ///при помощи массива задаем функцию с которой будем работать
45 }
46 cout<< "\n";
47
48 }
49
50 void interpol (double __start, double __ending, double __step) ///создаем функцию интерполяция с определением переменных
51 {
52
53 double amount1=((__ending-__start)/__step)+1; ///определяем тип и подсчитываем новое количество точек с новым шагом
54 int amounti=static_cast<int>(amount1); ///преобразуем количество из типа double к типу int
55
56 for (int i=0; i<amounti; i++) ///создаем цикл от 0 до amounti-нового количества точек
57 {
58
59 mass1=new double[amounti];
60 double x = i*__step+__start; ///определяем тип и расчитываем координату Х
61 double x0=(static_cast<int>((x-__start)/step)) * step+__start;///определяем тип и расчитываем координату х
62 ///в интерполирующейся точке, которая стоит до новой точки
63 double x1=x0+step;///определяем тип и расчитываем координату х1 прибавляя к предыдущей точке шаг
64 int i0=(static_cast<int>((x-__start)/step));///определяем значение массива в i0 соответстующей значению функции в x0
65 int i1=i0+1;
66 mass1[i]=(((x - x0 )*(mass[i1] - mass[i0]))/( x1-x0)) + mass[i0];
67 cout << "Х="<<i<<setw(10)<< "У= " << mass1[i] <<endl<<endl; ///выводим интерполяцию на экран
68 ofstream fout("interpol.txt",ios::app);///сохраняем в файл
69 fout<< "Х="<<i<<setw(10)<< "У="<<mass1[i]<<" \n";
70 fout.close();
71
72 }
73
74 amount=amounti;
75 delete []mass;
76 mass = mass1;
77
78 }
79
80 void aprocsimation(double __start, double __ending, double __step) ///создаем функцию апроксимация с определением переменных
81 {
82
83 int N=amount; ///определяем тип и значение переменной N (равна количеству точек с заданным шагом)
84 double SumXY=0; ///определяем тип и значение переменной SumXY ( сумма (Х*У) )
85 double SumX=0; ///определяем тип и значение переменной SumX ( сумма Х )
86 double SumY=0; ///определяем тип и значение переменной SumУ ( сумма У )
87 double Sum_Xkv=0; ///определяем тип и значение переменной Sum_Xkv ( сумма (Х*Х) )
88 double Xi; ///определяем тип переменной Xi
89
90 mass1 = new double[N]; ///создаем двумерный массив
91 for (int i=0; i<N; i++) ///создаем цикл от 0 до N (количество точек с заданным шагом)
92 {
93
94 Xi=i*__step+__start; ///расчитываем Хi
95 SumXY=SumXY+Xi*mass[i]; ///расчитываем SumXY
96 SumX=SumX+Xi; ///расчитываем SumX
97 SumY=SumY+mass[i]; ///расчитываем SumY
98 Sum_Xkv=Sum_Xkv+Xi*Xi; ///расчитываем Sum_Xkv
99
100 }
101
102 double a=(SumXY*N-SumX*SumY)/(N*Sum_Xkv-SumX*SumX); ///определяем тип и расчитываем коэффициент перед Х в уравнении аХ+b
103 double b=(SumY-a*SumX)/N; ///определяем тип и расчитываем свободный член в уравнении аХ+b
104
105 if (b>0) ///если b положительное то
106 cout<<"Апроксимация: "<<a<<"*x+"<<b<<endl; ///выводим на экран: Апроксимация: а*Х+b
107
108 else if (b<0) ///если b отрицательно то
109 cout<<"Апроксимация: "<<a<<"*x"<<b<<endl; ///выводим на экран: Апроксимация: а*Х b
110
111 for (int i=0; i<N; i++) ///создаем цикл от 0 до N (количество точек с заданным шагом)
112 {
113 mass1[i] = a*(i*__step+__start)+b; ///при помощи массива создаем функцию подсчета точек при апроксимации
114 }
115
116 delete[] mass;
117 mass=mass1;
118 vivod();///вывод на экран
119 zapis("aprocsimation.txt");///сохраненяем в файл
120
121 }
122
123 functya operator+ ( functya F) ///перегрузка оператора +
124 {
125
126 functya tmp(start,ending,step);
127
128 mass2=new double[amount];///создаем двумерный массив
129 for (int i=0; i<amount; i++)
130 {
131 mass2[i]=mass[i] + F.mass[i];///находим сумму двух функций
132 }
133 delete [] mass;
134 mass=mass2;
135 vivod();///выводим на экран результат
136 zapis("f3.txt");///сохраненяем в файл
137 cout<<"Введите шаг для интерполяции";
138 cin>>step2;
139 cout<<"Интерполяция: "<<"\n";
140 interpol(start,ending,step2);///вызов функции интерполяции
141 aprocsimation(start,ending,step2);///вызов функции аппроксимации
142 return tmp;
143
144 }
145
146 functya operator-( functya F)///перегрузка оператора -
147 {
148
149 functya tmp(start,ending,step);
150
151 mass2=new double[amount];///создаем двумерный массив
152 for (int i=0; i<amount; i++)
153 {
154 mass2[i]=mass[i] - F.mass[i];///находим разность двух функций
155 }
156
157 delete [] mass;
158 mass=mass2;
159 vivod();///выводим на экран результат
160 zapis("f3.txt");///сохраненяем в файл
161 cout<<"Введите шаг для интерполяции";
162 cin>>step2;
163 cout<<"Интерполяция: "<<"\n";
164 interpol(start,ending,step2);///вызов функции интерполяции
165 aprocsimation(start,ending,step2);///вызов функции аппроксимации
166 return tmp;
167
168 }
169
170 functya operator*( functya F)///перегрузка оператора *
171 {
172 functya tmp(start,ending,step);
173
174 mass2=new double[amount];///создаем двумерный массив
175 for (int i=0; i<amount; i++)
176 {
177 mass2[i]=mass[i] * F.mass[i];///находим произведение двух функций
178 }
179
180 delete [] mass;
181 mass=mass2;
182 vivod();///выводим на экран результат
183 zapis("f3.txt");///сохраненяем в файл
184 cout<<"Введите шаг для интерполяции";
185 cin>>step2;
186 cout<<"Интерполяция: "<<"\n";
187 interpol(start,ending,step2);///вызов функции интерполяции
188 aprocsimation(start,ending,step2);///вызов функции аппроксимации
189 return tmp;
190
191 }
192
193 functya operator/( functya F)///перегрузка оператора /
194 {
195
196 functya tmp(start,ending,step);
197
198 mass2=new double[amount];///создаем двумерный массив
199 for (int i=0; i<amount; i++)
200 {
201 mass2[i]=mass[i] / F.mass[i];///находим частное двух функций
202 }
203
204 delete [] mass;
205 mass=mass2;
206 vivod();///выводим на экран результат
207 zapis("f3.txt");///сохраненяем в файл
208 cout<<"Введите шаг для интерполяции ";
209 cin>>step2;
210 cout<<"Интерполяция: "<<"\n";
211 interpol(start,ending,step2);///интерполяция
212 aprocsimation(start,ending,step2);///вызов функции аппроксимации
213 return tmp;
214
215 }
216
217 void vivod ()///создаем функцию вывода на экран
218 {
219
220 for (int l=0; l<amount; l++)
221 {
222 cout<<"Х"<<l<<setw(10)<< "Y= " << mass[l] <<"\n";
223 }
224
225 }
226
227 void zapis (char Zapis[])///созданем функцию записи в файл
228 {
229
230 ofstream fout(Zapis);
231 for (int l=0; l<amount; l++)
232 {
233 fout<<"X="<<l<<setw(10)<<"Y="<<mass[l]<<" \n";
234 }
235
236 fout.close();
237
238 }
239
240 };
241
242 int main()
243 {
244
245 setlocale(LC_ALL,"RUS");
246
247 double start1, ending1, step1, step2;
248 int number;
249 cout<< "Введите начало отрезка ";
250 cin>> start1;
251 cout<< "Введите конец отрезка ";
252 cin>> ending1;
253 cout<<"Введите шаг для функций ";
254 cin>> step1;
255
256 functya F1(start1,ending1,step1);///создаем первую функцию
257 F1.massiv1();
258 F1.vivod();///выводим координаты первой функции на экран
259 F1.zapis("F1.txt");///записываем координаты первой функции в файл
260
261 cout<<"\n \n";
262
263 functya F2(start1,ending1,step1);///создаем вторую функцию
264 F2.massiv2();
265 F2.vivod();///выводим координаты второй функции на экран
266 F2.zapis("F2.txt");///записываем координаты второй функции в файл
267
268 cout<<"\n \n";
269
270 functya F3(start1, ending1, step1);
271
272 cout<<"Выберите, что вы хотите сделать с функциями: 1-найти сумму, 2-найти разность, 3-найти произведение, 4-найти частное ";
273 cin>>number;
274 cout<<"\n \n";
275
276 if(number==1)
277 {
278 F3=F1+F2;
279 }
280
281 else if (number==2)
282 {
283 F3=F1-F2;
284 }
285
286 else if (number==3)
287 {
288 F3=F1*(F2);
289 }
290
291 else if (number==4)
292 {
293 F3=F1/F2;
294 }
295
296 else
297 {
298 cout<<"Ошибка ";
299 }
300
301 return 0;
302
303 }
Инструкция к программе: пользователь вводит начало и конец отрезка и шаг для функций, после чего создается две функции. Затем функции суммируются, после чего пользователь вводит значение нового шага, суммированная функция интерполируется по новому шагу, после этого по МНК(методу наименьших квадратов) функция апроксимируется.
Скачать программу можно по ссылке
Метод наименьших квадратов задача состоит в том, чтобы минимизировать выражение: 1: http://mech.spbstu.ru/images/b/b0/003.png Доказано, что минимум достигается при: 2: http://mech.spbstu.ru/images/2/20/005.png записываем пункт 2 в нашу программу, находим коэффициенты и находим значение линейной функции y=ax+b, по интерполированным значениям x.
1 #include <iostream>
2 #include <math.h>
3 #include <iomanip>
4 #include<stdlib.h>
5 using namespace std;
6
7 class func
8 {
9 private:
10 double a/*начало*/,b/*конец*/,c/*шаг*/,k/**/,m/**/,rr/**/;
11 int d/*переменная для изменения типа, кол-во элементов для начальных элементов*/,tt/*переменная для изиенения типа, кол-ва элементов для счёта суммы*/;
12 double *F/*массив для значений У*/, *X/*Массив для значений Х*/, *R/*массив для значений У после интерполяции*/, *Q;
13 public:
14
15 func (double a1, double b1, double c1):a(a1),b(b1),c(c1)//создаём конструктор для функции
16 {
17 double p = (b-a)/c;
18 d = (int)p;
19 if (b > (d*c+a)) d += 2; //в зависимости от случая прибавляем либо 2 либо 1, чтобы не произошло переполнения массива
20 else d += 1;
21
22 F = new double [d];//создание динамического массива для У
23 X = new double [d];// создание динамического массива для Х
24 X[0]=a;//первый элемент
25 X[d-1]=b;//последний элемент, для того чтобы последний элемент был в конце промежутка, чтобы его не потерять
26 for(int i = 1; i < d-1; i++) X[i]=a+c*i; //присваивание значений всех Х
27
28 }
29 void first ()//функция для первой функции
30 {
31 double y;//в зависимости от случая прибавляем либо 2 либо 1, чтобы не произошло переполнения массива
32 F[0]=pow(2,a);//объявление значения У для начала промежутка
33 F[d-1]=pow(2,b);//объявление значения У для конца промежутка
34 for(int i = 1; i < d-1; ++i)
35 {
36 y = pow(2,((c*i)+a));//высчитываем значения У внутри промежутка
37 F[i] = y;//присваиваем массиву значения по У
38 }
39
40 cout << " " << endl;//пробел и конец строки
41 }
42
43 void second ()//функция для второй функции
44 {
45 if(a==0 || b==0) return;
46 F[0]=1*a*a; //присваивание значения функции в начале промежутка
47 F[d-1]=1*b*b;//присваивание значения функции в конце промежутка
48
49 for(int k = 1; k <d-1; ++k)
50 {
51 double n = c*k+a;
52 if (n != 0)//условие неделимости на ноль
53 {
54 F[k] = 1*n*n;
55 }
56 }
57
58 }
59
60 void operator +(func Q)//перегрузка оператора +
61 {
62 sum(Q);
63 }
64
65 void sum (func Q)//функция суммирования функций на интерполированном шаге
66 { double m, p = (b-a)/c;
67 int i;
68 R=new double[d+2];
69 if (b > (d*c+a)) d += 2; //в зависимости от случая прибавляем либо 2 либо 1, чтобы не произошло переполнения массива
70 else d += 1;
71 m=a;
72 cerr<<"\n";
73
74 for(i = 0; i <d-1; ++i)//цикл суммирования функций и вывода значений суммы, функций и иксов
75 {
76
77 cerr <<"YFirst: "<< F[i] << " ";
78 cerr << "YSecond: "<< Q.F[i] << " ";
79 R[i] = F[i] + Q.F[i];
80 cerr << "Ysum: "<< R[i] << " ";
81 cerr << "X:" << m << '\n';
82
83 m=m+c;
84 }
85 for(i = 0; i <d-1; ++i)
86 {Q.F[i]=R[i];
87 }
88 cerr << " " << endl;
89 }
90
91 double interp( double pnt/*новый шаг*/, func Q)//функция для интерполяции функции
92 {double p,h,i,w,*X,aApr,bApr,X2sm,XYsm,Xsm/*хранит сумму интерполированных иксов*/,Ysm/*хранит сумму интерполированных игреков*/;
93 int q,k,l,o;
94 p=(b-a)/pnt+1;
95 q=int(p);
96 R=new double [q];
97 X=new double [q];
98
99 l=0;
100 k=0;
101
102 for(h=a/*начало функции*/; h<=b/*конец функции*/; h=h+c/*старый шаг*/) //шагает по нормальному шагу
103 {
104 for(i=a-1; i<=b; i=i+pnt/*новый шаг*/)
105 if((i>h)&&(i<=(h+c)))//проверяет лежит ли новый шаг между точками старого
106 { R[k]=(Q.F[l]-Q.F[l-1])*(i-h)/c+Q.F[l-1];//формула интерполяции
107 cout<<"\n"<<"Yinter: "<<R[k]<<" "<<"X: "<<i-1;//вывод интерполированных значений и иксов
108 X[k]=i-1;
109 k++;
110 }
111 l++;
112 }
113 cout<<"\n";
114 cout<<"\n";
115 cout<<"\n";
116 //обнуление значений сумм для МНК
117 Xsm=0;
118 Ysm=0;
119 XYsm=0;
120 X2sm=0;
121
122 for(o=0;o<=k;o++)//цикл подготавливает суммы для МНК
123 {Xsm+=X[o];
124 Ysm+=R[o];
125 XYsm+=X[o]*R[o];
126 X2sm+=X[o]*X[o];
127 }
128
129 aApr=(k*XYsm-Xsm*Ysm)/(k*X2sm-Xsm*Xsm);//находим коэфициенты по МНК
130 bApr=(Ysm-a*Xsm)/k;
131 cout<<"\n"<<"aAprox"<<a<<" "<<"bAprox"<<b<<"\n";//выводим их
132 for(o=0;o<k;o++)
133 {c=aApr*X[o]+bApr;//считаем значение Y при данных коэфициентах
134 cout<<"YAprox: "<<c<<" "<<"X:"<<X[o]<<"\n" ;
135 }
136
137
138 return 0;}
139 };
140
141 int main(){
142 double x, xn, s1,pnt;
143 cout << "Input the beginning of the function: " << endl;
144 cin >> x;
145 cout << "Input the ending of the function: " << endl;
146 cin >> xn;
147 cout << "Input step for the function: " << endl;
148 cin >> s1;
149 func H(x,xn,s1);
150 H.first();
151 func G(x,xn,s1);
152 G.second();
153 H+G;
154 cout<<"\n" << "Input new step for the function: " << endl;
155 cin >> pnt;
156 H.interp(pnt,G);
157
158 return 0;}
Описание программы: программа, позволяющая складывать, вычитать, умножать и делить две функции, заданные на одном интервале, интерполирующая первую функцию по второй и аппроксимирующая результат арифметической операции с заданными пользователем функции.
Инструкция к программе: 1. Пользователь вводит параметры первой функции 2. Пользователь вводит параметры второй функции (при этом шаг второй функции меньше шага первой) 3. Происходит интерполяция первой функции по второй 4. Пользователь выбирает арифметическую операцию 5. При желании пользователь может выполнить аппроксимацию полученного результата
Скачать можно тут.
1 #ifndef FUNC_H
2 #define FUNC_H
3
4
5 class Func
6 {
7 public:
8 Func(double a1, double b1, double c1);
9 virtual ~Func();
10 void DefFunc (); // функция, определяющая количество элементов j на промежутке от a до b, с шагом c
11 void PluFunc (Func D); // функция, складывающая значения двух функций линейно (то есть значения первой функции при определенной переменной x складывается со значением второй функции при том же значении переменной)
12 void operator +(Func D); // перегрузка оператора '+'
13 void MinFunc (Func D); // функция, линейно вычитающая значения второй функции из значений первой функции
14 void operator -(Func D); // перегрузка оператора '-'
15 void UmnFunc (Func D); // функция, линейно переумножающая значения функций
16 void operator *(Func D); // перегрузка оператора '*'
17 void DelFunc (Func D); // функция, линейно делящая значения первой функци на значения второй функции
18 void operator /(Func D); // перегрузка оператора '/'
19 void In (Func D); // функция, интерполирующая первую функцию по второй
20 void App (); // функция, аппроксимирующая полученную в результате сложения/вычитания/деления/умножения двух функций функцию
21 void Viv (); // Функция вывода на экран значений
22 protected:
23 private:
24 double a,b,c;
25 int j,z;
26 double *A,*B;
27 };
28
29 #endif // FUNC_H
30
31
32
33 #include "Func.h"
34 #include <fstream>
35 #include <iostream>
36 #include <math.h>
37
38 Func::Func(double a1, double b1, double c1):a(a1),b(b1),c(c1) // конструктор для класса Func, создающий объект данного класса, определенный тремя значениями, введенными пользователем
39 {
40 double d=(b-a)/c; // расчет количества элементов, определяющих функцию
41 j=floor(d); // созданной целочисленной переменной присваивается значение, равное целой части числа, рассчитанного выше, с округлением в меньшую сторону
42 A = new double [j+1]; // создание массива
43 }
44
45 Func::~Func() // деструктор для класса Func
46 {
47 //dtor
48 }
49
50 void Func::Viv () // Функция вывода на экран значений
51 {
52 std::cout << "x ";
53 for (int z=0; z<=j; ++z)
54 {
55 std::cout << z+1 << " ";
56 }
57 }
58
59 void Func::DefFunc () // функция, определяющая количество элементов j на промежутке от a до b, с шагом c
60 {
61 double x; // создание переменной, используемой для расчета значений функции
62 for(int i=0; i<=j; ++i) // создание цикла, рассчитывающего j элементов
63 {
64 x =i*c+a; // задание значения перемнной x, определенной выше
65 A[i]=x*x; // задание значения самой функции (при этом в данной ситуации нам неважно, как именно задается функция, ее значения могут быть определены любым способом, от этого алгоритм не меняется)
66 std::cerr << A[i] << " "; // вывод на экран значения функции
67 }
68 }
69
70 void Func::PluFunc (Func D) // функция, складывающая значения двух функций линейно (то есть значения первой функции при определенной переменной x складывается со значением второй функции при том же значении переменной)
71 {
72 std::ofstream out("zap.txt"); // открытие файла "zap.txt", находящегося в той же папке, что и программа, для работы
73 for(int i=0; i<=D.j; ++i) // создание цикла, повторяющегося (D.j+1) раз
74 {
75 B[i]=B[i]+D.A[i]; // сложение значений двух функций для одного и того же значения переменной
76 }
77 for (int i=0; i<=D.j; ++i) // создание цикла, рассчитанного на то же количество раз, что и предыдущий
78 {
79 out << B[i] << '\n'; // запись значений, полученных в предыдущем цикле, в файл
80 }
81 out.close(); // закрытие файла после записи в него значений
82 D.Viv();
83 std::cout << std::endl << "y ";
84 for (int i=0; i<=D.j; ++i) // аналогичный предыдущему цикл, выводящий значения на экран
85 {
86 std::cout << B[i] << " ";
87 }
88 }
89 void Func::operator +(Func D) // перегрузка оператора '+'
90 {
91 PluFunc(D); // с помощью данного куска программы мы позволяем записать функцию в несколько ином виде: теперь запись f1+f2 будет работать аналогично записи f1.PluFunc(f2)
92 }
93 void Func::MinFunc (Func D) // функция, линейно вычитающая значения второй функции из значений первой функции
94 {
95 std::ofstream out("zap.txt"); // открытие файла "zap.txt", находящегося в той же папке, что и программа, для работы
96 for(int i=0; i<=D.j; ++i) // создание цикла, повторяющегося (D.j+1) раз
97 {
98 B[i]=B[i]-D.A[i]; // вычитание значений второй функций из значений первой для одного и того же значения переменной
99 }
100 for (int i=0; i<=D.j; ++i) // создание цикла, рассчитанного на то же количество раз, что и предыдущий
101 {
102 out << B[i] << '\n'; // запись значений, полученных в предыдущем цикле, в файл
103 }
104 out.close(); // закрытие файла после записи в него значений
105 D.Viv();
106 std::cout << std::endl << "y ";
107 for (int i=0; i<=D.j; ++i) // аналогичный предыдущему цикл, выводящий значения на экран
108 {
109 std::cout << B[i] << " ";
110 }
111 }
112 void Func::operator -(Func D) // перегрузка оператора '-'
113 {
114 MinFunc(D); // с помощью данного куска программы мы позволяем записать функцию в несколько ином виде: теперь запись f1-f2 будет работать аналогично записи f1.MinFunc(f2)
115 }
116 void Func::UmnFunc (Func D) // функция, линейно переумножающая значения функций
117 {
118 std::ofstream out("zap.txt"); // открытие файла "zap.txt", находящегося в той же папке, что и программа, для работы
119 for(int i=0; i<=D.j; ++i) // создание цикла, повторяющегося (D.j+1) раз
120 {
121 B[i]=B[i]*D.A[i]; // умножение значений первой функций на значенийя второй для одного и того же значения переменной
122 }
123 for (int i=0; i<=D.j; ++i) // создание цикла, рассчитанного на то же количество раз, что и предыдущий
124 {
125 out << B[i] << '\n'; // запись значений, полученных в предыдущем цикле, в файл
126 }
127 out.close(); // закрытие файла после записи в него значений
128 D.Viv();
129 std::cout << std::endl << "y ";
130 for (int i=0; i<=D.j; ++i) // аналогичный предыдущему цикл, выводящий значения на экран
131 {
132 std::cout << B[i] << " ";
133 }
134 }
135 void Func::operator *(Func D) // перегрузка оператора '*'
136 {
137 UmnFunc(D); // с помощью данного куска программы мы позволяем записать функцию в несколько ином виде: теперь запись f1*f2 будет работать аналогично записи f1.UmnFunc(f2)
138 }
139 void Func::DelFunc (Func D) // функция, линейно делящая значения первой функци на значения второй функции
140 {
141 std::ofstream out("zap.txt"); // открытие файла "zap.txt", находящегося в той же папке, что и программа, для работы
142 for(int i=0; i<=D.j; ++i) // создание цикла, повторяющегося (D.j+1) раз
143 {
144 B[i]=B[i]/D.A[i]; // деление значений первой функций на значенийя второй для одного и того же значения переменной
145 }
146 for (int i=0; i<=D.j; ++i) // создание цикла, рассчитанного на то же количество раз, что и предыдущий
147 {
148 out << B[i] << '\n'; // запись значений, полученных в предыдущем цикле, в файл
149 }
150 out.close(); // закрытие файла после записи в него значений
151 D.Viv();
152 std::cout << std::endl << "y ";
153 for (int i=0; i<=D.j; ++i) // аналогичный предыдущему цикл, выводящий значения на экран
154 {
155 std::cout << B[i] << " ";
156 }
157 }
158 void Func::operator /(Func D) // перегрузка оператора '/'
159 {
160 DelFunc(D); // с помощью данного куска программы мы позволяем записать функцию в несколько ином виде: теперь запись f1/f2 будет работать аналогично записи f1.DelFunc(f2)
161 }
162 void Func::In (Func D) // функция, интерполирующая первую функцию по второй
163 {
164 double l=c/D.c; // создаем переменную, которой присваиваем значение, обозначающее, во сколько раз один шаг больше другого
165 c=D.c; // приводим больший шаг к меньшему значению
166 z=D.j+1; // ранее созданной переменной присваиваем значение, равное количеству элементов плюс один
167 int p=l; // создаем целочисленную переменную, равную переменной l
168 B = new double [D.j+2]; // создание массива с количеством элементов D.j+2
169 D.Viv(); std::cout << std::endl << "y ";
170 B[0]=A[0]; std::cerr << B[0] << " "; // присваиваем первому элементу нового массива значение первого элемента старого массива и выводим его на экран
171 int k=0; // создаем вспомогательную целочисленную переменную
172 for (int i=0; i<=j; i+=p) // создаем цикл, рассчитанный на j повторов через p
173 {
174 for (int m=1; m<p; ++m) // создание цикла, выссчитывавшего промежуточное значение
175 {B[i+m]=((A[k]+A[k+1])/p)*(l-m); std::cerr << B[i+m] << " ";} // присваиваем (i+m)-ому элементу значение, выссчитанного по формуле через заданные изначально значения и вывод егона экран
176 B[i+p]=A[k+1]; // присваивание значению (i+p)-ого элемента нового массива значения (k+1)-ого элемента старого массива
177 std::cerr << B[i+p] << " "; // вывод высчитанного выше значения на экран
178 k=k+1; // увеличение k на единицу
179 }
180 }
181 void Func::App () // функция, аппроксимирующая полученную в результате сложения/вычитания/деления/умножения двух функций функцию
182 {
183 double d=0,e=0,f=0,g=0; // создание переменных
184 double k=0,l=0; // создание переменных
185 for (int i=0; i<z; ++i) // цикл, который высчитывает сумму произведений зависимой и независимой переменных
186 {d=i*B[i]+d;}
187 for (int i=0; i<z; ++i) // цикл, который высчитывает сумму всех значений функции
188 {e=B[i]+e;}
189 for (int i=0; i<z; ++i) // цикл, высчитывающий сумму всех аргументов функции
190 {f=i+f;}
191 for (int i=0; i<z; ++i) // цикл, высчитывающий сумму квадратов всех аргументов функции
192 {g=i*i+g;}
193 k=(z*d-f*e)/(z*g-f*f); // расчет углового коэффициента прямой
194 l=(e-k*f)/z; // расчет свободного коэффициента прямой
195 std::cout << "y=" << k << "x+" << l; // вывод уравнения полученной прямой на экран
196 std::ofstream out("ap.txt"); // запись полученного уравнения в файл
197 {
198 out << "y=" << k << "x+" << l;
199 }
200 out.close();
201 }
202
203
204
205 #include <iostream>
206 #include <fstream>
207 #include "Func.h"
208
209 using namespace std;
210 double m,n,o, m1, n1, o1;
211 int a;
212 char b;
213
214 int main()
215 {
216 cout << "Enter the beginning, the end and the step of a function." << endl; // ввод опорных значений первой функции: начало, конец, шаг;
217 cin >> m >> n >> o; // считывание значений
218 cout << "Enter the beginning, the end and the step of another function." << endl; // ввод опорных значений второй функции: начало, конец, шаг;
219 cin >> m1 >> n1 >> o1; // считывание значений
220 Func F(m,n,o); // создание объекта класса Func, определяющий первую функцию
221 cout << "The first function is" << endl; F.Viv(); cout << endl << "y ";
222 F.DefFunc(); // определение первой функции через создание массива с ее значениями
223 cout << endl;
224 Func F1(m1,n1,o1); // создание объекта класса Func, определяющий вторую функцию
225 cout << "The second function is" << endl; F1.Viv(); cout << endl << "y ";
226 F1.DefFunc(); // определение второй функции через создание массива с ее значениями
227 cout << endl;
228 cout << "As two functions have different steps, we made the interpolation of the first function." << endl;
229 F.In(F1); // линейная интерполяция первой функции по второй
230 cout << endl;
231 cout << "What do you want to do with these functions?" << '\n' << "Enter 1 to sum them;" << '\n' << "Enter 2 to subtract the second from the first;" << '\n' << "Enter 3 to multiply them;" << '\n' << "Enter 4 to divide first by second" << endl;
232 cin >> a;
233 if (a==1)
234 {cout << "Function 1 + function 2 =" << '\n'; F+F1;} // сложение двух функций с одинаковым шагом и интервалом
235 else if (a==2)
236 {cout << "Function 1 - function 2 =" << '\n'; F-F1;} // вычитание двух функций с одинаковым шагом и интервалом
237 else if (a==3)
238 {cout << "Function 1 * function 2 =" << '\n'; F*F1;} // умножение двух функций с одинаковым шагом и интервалом
239 else if (a==4)
240 {cout << "Function 1 / function 2 =" << '\n'; F/F1;} // деление двух функций с одинаковым шагом и интервалом
241 cout << endl;
242 cout << "Enter 5 to do the approximation of the result function" << endl; // пользователь сам выбирает, выполнять ли аппроксимацию;
243 cout << "Otherwise enter 6 to quit" << endl;
244 cin >> a;
245 if (a==5)
246 {cout << "Appromaximation:" << endl;
247 F.App();} // аппроксимация
248 return 0;
249 }
Краткое описание алгоритма : Программа создаёт и хранит значения двух функций с одинаковом шагом и заданных на одинаковом интервале. Методы позволяют сложить эти две функции,интерполировать одну из них по заданному шагу или апроксимировать методом наименьших квадратов. Данные берутся из файла. При считывании с файла сначала указывается отрезок, потом величина, а потом дискретные значения.
1 #include <stdio.h>
2 #include <stdlib.h>
3 //Бибилотека необходимая для возможности включения русского языка в консоли
4 #include <locale.h>
5
6 class fun
7 {
8 /*
9 fx - массив с дискретными значениями функции
10 a - начало отрезка определения функции
11 b - конец отрезка определения функции
12 dx - шаг
13 */
14 double *fx, a, b, dx;
15 //Чтобы очусть ошибки округления в вещественных числах при сравнениях используется константа eps.
16 //К примеру два вещественных числа x и y сравниваются не так x>=y, а так x-y>=-eps.
17 const double eps = 1e-10; //1e-10 это тоже самое что 0.0000000001
18
19 public:
20 //Коструктор по умолчанию
21 fun();
22 //Конструктор копирования
23 fun(fun &tmp);
24 //Деструктор
25 ~fun();
26
27 //Перегруженные операторы. Ключевое слово const в конце означает, что объект от которого вызвается метод не изменяется
28 const fun operator+(const fun& right) const;
29 const fun operator-(const fun& right) const;
30 const fun operator*(const fun& right) const;
31 const fun operator/(const fun& right) const;
32 const fun& operator=(const fun& right);
33
34 //Метод считывания из файла
35 void readFile(const char *path);
36 //Метод вывода в файл
37 void writeFile(const char *path);
38
39 //Метод изменения шага
40 void changeDx(double newDx);
41 //Метод вычисления значения в заданной точке
42 double getX(double x1);
43 };
44
45 //В конструкторе по умолчанию все просто.
46 fun::fun()
47 {
48 a = b = dx = 0;
49 fx = NULL;
50 }
51
52 //Конструктор копирования
53 fun::fun(fun &tmp)
54 {
55 int i, n;
56 //Копирование свойств объекта tmp в текущий объект
57 a = tmp.a;
58 b = tmp.b;
59 dx = tmp.dx;
60 //Вычисление количества дискретных значений
61 n = (b - a) / dx + 1;
62 //Выделение необходимой памяти для хранения дискретных значений
63 fx = new double[n];
64 //Копирование дискретных значений объекта tmp в текущий объект
65 for (i = 0; i<n; ++i)
66 fx[i] = tmp.fx[i];
67 }
68
69 //Деструктор
70 fun::~fun()
71 {
72 //Освобождение памяти выделенной для массива дискретных значений
73 if (fx != NULL) delete[] fx;
74 }
75 //Оператор сложения.
76 const fun fun::operator+(const fun& right) const
77 {
78 //Создание результирующего объекта
79 fun result;
80 int i, n;
81 //Копирование свойств в результирующий объект
82 result.dx = dx;
83 result.a = a;
84 result.b = b;
85 //Вычисление количества дискретных значений
86 n = (b - a) / dx + 1;
87 //Выделение необходимой памяти для хранения дискретных значений
88 result.fx = new double[n];
89 //Вычисление дискретных значений результирующего объекта
90 for (i = 0; i<n; ++i)
91 result.fx[i] = fx[i] + right.fx[i];
92
93 //Возвращение результата
94 return result;
95 }
96
97 //Этот оператор аналогичен оператору сложение
98 const fun fun::operator-(const fun& right) const
99 {
100 fun result;
101 int i, n;
102 result.dx = dx;
103 result.a = a;
104 result.b = b;
105 n = (b - a) / dx + 1;
106 result.fx = new double[n];
107 for (i = 0; i<n; ++i)
108 result.fx[i] = fx[i] - right.fx[i];
109
110 return result;
111 }
112
113 //Этот оператор аналогичен оператору сложение
114 const fun fun::operator*(const fun& right) const
115 {
116 fun result;
117 int i, n;
118 result.dx = dx;
119 result.a = a;
120 result.b = b;
121 n = (b - a) / dx + 1;
122 result.fx = new double[n];
123 for (i = 0; i<n; ++i)
124 result.fx[i] = fx[i] * right.fx[i];
125
126 return result;
127 }
128
129 //Этот оператор аналогичен оператору сложение
130 const fun fun::operator/(const fun& right) const
131 {
132 fun result;
133 int i, n;
134 result.dx = dx;
135 result.a = a;
136 result.b = b;
137 n = (b - a) / dx + 1;
138 result.fx = new double[n];
139 for (i = 0; i<n; ++i)
140 result.fx[i] = fx[i] / right.fx[i];
141
142 return result;
143 }
144
145 //Оператор присваивания
146 const fun& fun::operator=(const fun& right)
147 {
148 //Проверка на самоприсваивание
149 if (this == &right)
150 //Возвращение в качестве результата текущий объект
151 return *this;
152
153
154 int i, n;
155 //Присваивание свойств объекта right текущему объекту
156 a = right.a;
157 b = right.b;
158 dx = right.dx;
159 //Вычисление количества дискретных значений
160 n = (b - a) / dx + 1;
161 //Если в текущем объекте есть какие-то дискретные значения, то их нужно удалить. То есть удалить память выделенную под них
162 if (fx != NULL) delete[] fx;
163 //Выделение необходимой памяти для хранения дискретных значений
164 fx = new double[n];
165
166 //Копирование дискретных значений объекта right в текущий объект
167 for (i = 0; i<n; ++i)
168 fx[i] = right.fx[i];
169
170 //Возвращение в качестве результата текущий объект
171 return *this;
172 }
173
174 /*
175 Метод считывания из файла
176 path - путь к файлу из которого считывать
177 */
178
179 void fun::readFile(const char *path)
180 {
181 //Открытие файла для считывания
182 FILE *in = fopen(path, "r");
183 int i, n;
184 //Считывание границ отрезка и шага из файла
185 fscanf(in, "%lf%lf%lf", &a, &b, &dx);
186 //Вычисление количества дискретных значений
187 n = (b - a) / dx + 1;
188 //Если в текущем объекте есть какие-то дискретные значения, то их нужно удалить. То есть удалить память выделенную под них
189 if (fx != NULL) delete[] fx;
190 //Выделение необходимой памяти для хранения дискретных значений
191 fx = new double[n];
192 //Считывание дискретных значений из файла
193 for (i = 0; i<n; ++i) fscanf(in, "%lf", &fx[i]);
194 //Закрытие файла
195 fclose(in);
196 }
197
198 /*
199 Метод вывода в файл
200 path - путь к файлу в который нужно вывести
201 */
202
203 void fun::writeFile(const char *path)
204 {
205 //Открытие файла для вывода
206 FILE *out = fopen(path, "w");
207 int i, n;
208 double x = a;
209 //Вычисление количества дискретных значений
210 n = (b - a) / dx + 1;
211 //Вывод информации о отрезке и шаге в файл
212 fprintf(out, "[%.5lf, %.5lf] dx=%.5lf\n", a, b, dx);
213 //Последовательный вывод пары (точка, значение в точке) в файл
214 for (i = 0; i<n; ++i, x += dx)
215 fprintf(out, "x=%.5lf f(x)=%.5lf\n", x, fx[i]);
216 //Закрытие файла
217 fclose(out);
218 }
219
220 /*
221 Метод изменения величины шага
222 */
223 void fun::changeDx(double newDx)
224 {
225 int i, j, n, newN;
226 double *newFx, x, newX, x1, y1, x2, y2, K, B;
227 //Вычисление количества старых дискретных значений
228 n = (b - a) / dx + 1;
229 //Вычисление количества новых дискретных значений
230 newN = (b - a) / newDx + 1;
231 //Выделение памяти под новые дискретные значения
232 newFx = new double[newN];
233 //Определение первой точки в которой вычисляется новое дискретное значение
234 newX = a;
235 //Переменная которая бежит по старым дискретным значениям
236 i = 0;
237 //Определение первой точки в которой вычисляется старое дискретное значение
238 x = a;
239 //Цикл для формирования новых дискретных значений
240 for (j = 0; j<newN; ++j, newX += newDx)
241 {
242 //В цикле находим отрезок где лежит точка в которой нужно вычислить новое дискретное значение
243 for (; i<n - 1; ++i, x += dx)
244 //Если без eps, то сравнения такие: x<=newX<=x+dx
245 if ((newX - x>-eps) && ((x+dx) - newX>-eps))
246 {
247 //Линейная интерполяция
248 x1 = x;
249 x2 = x + dx;
250 y1 = fx[i];
251 y2 = fx[i + 1];
252 K = (y2 - y1) / (x2 - x1);
253 B = (y2*x1 - y1*x2) / (x1 - x2);
254 //Вычисления значения в точке с помощью линейной интерполяции
255 newFx[j] = newX*K + B;
256 //Выход из цикла по i
257 break;
258 }
259 }
260 //Смена величины шага на новый
261 dx = newDx;
262 //Удаление старых дискретных значений
263 delete[] fx;
264 //Присвоение текущему объекту новых дискретных значений
265 fx = newFx;
266 }
267
268 /*
269 Метод вычисляет значение в точке xAns с помощью линейной интерполяции.
270 */
271 double fun::getX(double xAns)
272 {
273 int i, n;
274 double x, x1, y1, x2, y2, K, B;
275 x = a;
276 //Вычисление количества дискретных значений
277 n = (b - a) / dx + 1;
278 //Ищем отрезок в котором лежит точка xAns
279 for (i = 0; i<n - 1; ++i, x += dx)
280 {
281 //Если без eps, то сравнения такие: x<=newX<=x+dx
282 if (((x+dx) - xAns>-eps) && (xAns - x>-eps))
283 {
284 //Линейная интерполяция
285 x1 = x;
286 x2 = x + dx;
287 y1 = fx[i];
288 y2 = fx[i + 1];
289 K = (y2 - y1) / (x2 - x1);
290 B = (y2*x1 - y1*x2) / (x1 - x2);
291 //Вычисления значения функции в заданной точке с помощью линейной интерполяции
292 return K*xAns + B;
293 }
294 }
295 }
296
297 int main()
298 {
299 //Включение поддержки русского языка в консоли
300 setlocale(LC_ALL, "Russian");
301 //Объявление трех переменных типа fun
302 fun a, b, c;
303 //Считывания первых дискретных значений из файла inputA.txt
304 a.readFile("inputA.txt");
305 //Считывания вторых дискретных значений из файла inputB.txt
306 b.readFile("inputB.txt");
307
308 //Первая функция
309 a.writeFile("outputA.txt");
310 //Вторая функция
311 b.writeFile("outputB.txt");
312
313 c = a + b;
314 //Результат сложения двух функций
315 c.writeFile("outputAaddB.txt");
316
317
318 c = a - b;
319 //Результат вычитания второй функции из первой
320 c.writeFile("outputAsubB.txt");
321
322 c = a*b;
323 //Результат умножения двух функций
324 c.writeFile("outputAmultiB.txt");
325
326 c = a / b;
327 //Результат деления первой функции на вторую
328 c.writeFile("outputAdivB.txt");
329
330 //У первой функции изменили шаг на 0.5
331 a.changeDx(0.5);
332 //Вывели её дискретные значения
333 a.writeFile("outputChangeDx.txt");
334
335 //Функция, которая аппроксимирует её кусочно линейная.
336 //Для примера нашли значение аппроксимируещей функции в точке не совпадающей с дискретными значениями.
337 printf("Значение в точке 1.8 первой функции %.5lf\n", a.getX(1.8));
338
339 //Нужно чтобы окно консоли автоматически не закрылось
340 system("pause");
341 return 0;
342 }
Скачать можно здесь
Краткое описание алгоритма : Программа создаёт и хранит значения двух функций с одинаковом шагом и заданных на одинаковом интервале.Методы позволяют сложить эти две функции,интерполировать одну из них по заданному шагу или апроксимировать,методом наименьших квадратов.Данныеберутся из файла.
1 #include <iostream>
2 #include <vector>
3 #include <math.h>
4 #include <fstream>
5 #include <stdio.h>
6 #include <string>
7 #include <time.h>
8
9 using namespace std;
10
11 class func {
12 vector <double> vals;
13 double a, b, step, sz;
14
15 public:
16 func (string fil) { //конструктор для ввода функции из файла
17 ifstream f(fil.c_str());
18 double a, b, step, y;
19 f >> a >> b >> step; //вводим основные значения из файла
20 this->step = step;
21 this->sz = (int)((b - a) / step + 1); //считаем размер
22 this->a = a, this->b = b;
23 for (int i = 0; i < this->sz; i++) {
24 f >> y;
25 this->vals.push_back(y); //считываем и записываем значения из файла
26 }
27 f.close();
28 }
29 func () {} //еще один конструктор
30 func operator + (func a) { // эта и ближайшие четыре метода -- калькулятор функций
31 func f = *new func(); //создаем новый экземпляр класса, ответ
32 for (int i = 0; i < sz; i++) {
33 f.vals.push_back(this->vals[i] + a.vals[i]); // складываем покоординатно
34 }
35 f.step = a.step; // копируем все значения в ответ (возможно, это можно сделать гораздо проще и не писать 4*4 строк но почему-то ничего умнее я не придумал)
36 f.a = a.a;
37 f.b = a.b;
38 f.sz = a.sz;
39 return f;
40 }
41 func operator - (func a) {
42 func f = *new func();
43 for (int i = 0; i < a.sz; i++) {
44 f.vals.push_back(this->vals[i] - a.vals[i]);
45 }
46 f.step = a.step;
47 f.a = a.a;
48 f.b = a.b;
49 f.sz = a.sz;
50 return f;
51 }
52 func operator * (func a) {
53 func f = *new func();
54 for (int i = 0; i < a.sz; i++) {
55 f.vals.push_back(this->vals[i] * a.vals[i]);
56 }
57 f.step = a.step;
58 f.a = a.a;
59 f.b = a.b;
60 f.sz = a.sz;
61 return f;
62 }
63 func operator / (func a) {
64 func f = *new func();
65 for (int i = 0; i < a.sz; i++) {
66 f.vals.push_back(this->vals[i] / a.vals[i]);
67 }
68 f.step = a.step;
69 f.a = a.a;
70 f.b = a.b;
71 f.sz = a.sz;
72 return f;
73 }
74
75 pair<double, double> approx() { //аппроксимация. это все из наших лаб по физике, тут сплошная математика, никакого программирования
76 double mid = 0;
77 for (int i = 0; i < this->sz; i++) {
78 mid += this->a + i * this->step;
79 }
80 mid /= this->sz;
81 double d = 0;
82 for (int i = 0; i < this->sz; i++) {
83 d += pow((this->a + i * this->step - mid), 2.);
84 }
85 double a = 0;
86 for (int i = 0; i < this->sz; i++) {
87 a += (this->a + i * this->step - mid) * this->vals[i];
88 }
89 a /= d;
90 double midy = 0;
91 for (int i = 0; i < this->sz; i++) {
92 midy += this->vals[i];
93 }
94 midy /= this->sz;
95 double c = midy - a * mid;
96 return {a, c}; //{x,y} возвращает пару (на самом деле не пару а просто какой-нибудь объект) с первым значением x и вторым y
97 }
98
99 func inter(double step) {
100 func f = *new func(); //ответ
101 double curr2, curr1;
102 int j = 0;
103 f.a = this->a, f.b = this->b, f.step = step, f.sz = (int)((b - a) / step + 1);
104 for (int i = 0; i < f.sz; i++) {
105 curr2 = a + i * step;
106 curr1 = a + j * this->step;
107 while (curr1 + this->step <= curr2) {
108 j++, curr1 += this->step;
109 }
110 if (curr1 == curr2) {
111 f.vals.push_back(this->vals[j]);
112 continue;
113 }
114 f.vals.push_back((this->vals[j + 1] - this->vals[j]) * (curr2 - curr1) / this->step + this->vals[j]);//я хз, тут видимо какая-то математика
115 }
116 return f;
117 }
118 void write(string fil) { //запись. чтобы записать не в файл, а в консоль вывести, надо передать "-1"
119 ofstream f(fil.c_str());
120 if (fil != "-1") {
121 f << this->a << ' ' << this->b << ' ' << this->step << '\n';
122 }
123 else
124 cout << this->a << ' ' << this->b << ' ' << this->step << '\n';
125 for (int i = 0; i < sz; i++) {
126 if (fil != "-1")
127 f << this->vals[i] << '\n';
128 else
129 cout << this->vals[i] << '\n';
130 }
131 f.close();
132
133 }
134 };
135
136 int main() {
137 string fil;
138 cout << "Input the file name with the function values\n";
139 cin >> fil;
140 func f = *new func(fil);
141 int a;
142 char ch;
143 double st;
144 while (true) {
145 cout << "what do you want to do?\n1-math operation\n2-interpolation\n3-approximation\n4-write to file\n5-read values from file\n6-quit\n";
146 cin >> a;
147 if (a == 4) {
148 cout << "input file name to write to\n";
149 cin >> fil;
150 f.write(fil);
151 }
152 if (a == 3) {
153 auto t = f.approx();
154 cout << "Approximate line equation is y = " << t.first << " * x + " << t.second << '\n';
155 }
156 if (a == 2) {
157 cout << "input step to interpolate\n";
158 cin >> st;
159 f = f.inter(st);
160 }
161 if (a == 1) {
162 cout << "input arithmetic operator and file name with the second function values\n";
163 cin >> ch >> fil;
164 if (ch == '+') f = f + func(fil);
165 if (ch == '-') f = f - func(fil);
166 if (ch == '*') f = f * func(fil);
167 if (ch == '/') f = f / func(fil);
168 }
169 if (a == 5) {
170 cout << "Input the file name with the function values\n";
171 cin >> fil;
172 f = *new func(fil);
173 }
174 if (a == 6)
175 return 0;
176 }
177 }
Нарядчиков Александр
Инструкция: Пользователю достаточно просто запустить программу.
Описание программы: В окне рисуются графики с разным шагом, количеством точек, начальными и конечными координатами, по клавише 'G' происходит их кубическая интерполяция, также рисуется график их суммы. По клавише 'S' можно сохранить полученный график в текстовый документ в виде координат его точек. По клавише 'L' можно загрузить график из текстового документа, и он появится в окне программы. Также происходит линейная аппроксимация графика суммы, и график аппроксимации рисуется на экран.
Описание алгоритма: Вся графика написана с помощью библиотек OpenGL и GLUT. Кубическая интерполяция написана с помощью кривых Безье(интерполяция по четырем точкам - кубическая кривая). При сложение двух графиков происходит их интерполяция, для приведения их к общему шагу. Линейная аппроксимация написана с помощью метода наименьших квадратов.
"T05GRAPH.CPP"
1 /* FILENAME: T05GRAPH.CPP
2 * LAST UPDATE: 17.01.2016
3 */
4
5 #include "GRAPH.H"
6
7 /* Глобальные переменные */
8 // Глобальная переменная, хранящая время в секундах с момента старта программы
9 double SyncTime;
10 // Глобальные переменные для отслеживания нажатия клавиш
11 bool IsGraph, IsSave, IsLoad, IsLoaded;
12
13 /* Timer function */
14 // Подсчет времени
15 void Timer( void )
16 {
17 long t;
18 static long StartTime = -1;
19
20 t = clock();
21 if (StartTime == -1)
22 StartTime = t;
23 SyncTime = (double)(t - StartTime) / CLOCKS_PER_SEC;
24 } /* End of 'Timer' function */
25
26 /* Display function */
27 // Стандартная функция, вызываемая при перерисовке окна
28 void Display( void )
29 {
30 graph G1(-15, 15, 0.1), G2(2, 10, 0.4), G3, G4;
31
32 // Запуск времени
33 Timer();
34
35 // Установка цвета закраски фона в белый
36 glClearColor(1, 1, 1, 1);
37 // Очищаем цветовой буфер для создания нового изображения
38 glClear(GL_COLOR_BUFFER_BIT);
39
40 glLoadIdentity();
41 glScaled(0.1 / (1366 / 768.0), 0.1, 0.1);
42
43 // Отрисовка осей X и Y
44 glBegin(GL_LINE_STRIP);
45
46 glColor3d(0, 0, 1);
47 glVertex2d(0, -1000);
48 glVertex2d(0, 1000);
49
50 glColor3d(1, 0, 0);
51 glVertex2d(-1000, 0);
52 glVertex2d(1000, 0);
53
54 glEnd();
55
56 /* Отрисовка графиков */
57 // Отрисовка первого графика и его интерполяция по клавише "G"
58 G1.Draw(sin);
59 if (IsGraph == 1)
60 G1.Interpolation_Draw(1.0 / 32);
61
62 // Отрисовка второго графика и его интерполяция по клавише "G"
63 G2.Draw(log);
64 if (IsGraph == 1)
65 G2.Interpolation_Draw(1.0 / 32);
66
67 // Отрисовка графика суммы для первого и второго графиков
68 G3 = G2 + G1;
69 glColor3d(0, 1, 0);
70 G3.Draw();
71 // Аппроксимация графика суммы
72 G3.Approximation();
73
74 // Сохранение графика по клавише "S"
75 if (IsSave == 1)
76 {
77 G3.SaveArray();
78 IsSave == 0;
79 }
80
81 // Загрузка графика по клавише "L"
82 if (IsLoad == 1)
83 {
84 delete[] G4.mas;
85 delete[] G4.Color;
86 G4.LoadArray("graph.txt");
87 IsLoad == 0;
88 IsLoaded = 1;
89 }
90
91 // Отрисовка загруженного графика
92 if (IsLoaded == 1)
93 {
94 glColor3d(1, 0, 0);
95 G4.Draw();
96 IsLoaded = 0;
97 }
98
99 // Чистка памяти
100 delete[] G1.mas;
101 delete[] G1.Color;
102 delete[] G2.mas;
103 delete[] G2.Color;
104 delete[] G3.mas;
105 delete[] G3.Color;
106 delete[] G4.mas;
107 delete[] G4.Color;
108
109 glFinish();
110 // Копируем вторичный буфер в окно
111 glutSwapBuffers();
112 // Вызываем функцию обновления кадра
113 glutPostRedisplay();
114 } /* End of 'Display' function */
115
116 /* Keyboard function */
117 // Стандартная функция, вызываемая при нажатие клавиш на клавиатуре
118 void Keyboard( unsigned char Key, int X, int Y )
119 {
120 // Выход из программы
121 if (Key == 27)
122 exit(0);
123 // Отрисовка интерполированных графиков
124 else if ((Key == 'G') || (Key == 'g'))
125 IsGraph = !IsGraph;
126 // Сохранение графика суммы в файл
127 else if ((Key == 'S') || (Key == 's'))
128 IsSave = !IsSave;
129 // Загрузка графика из файла
130 else if ((Key == 'L') || (Key == 'l'))
131 IsLoad = !IsLoad;
132 // Открытие программы в полном экране
133 else if ((Key == 'F') || (Key == 'f'))
134 glutFullScreen();
135 } /* End of 'Keyboard' function */
136
137 /* Main function */
138 int main( int argc, char *argv[] )
139 {
140 // Инициализации OpenGL и GLUT
141 glutInit(&argc, argv);
142 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
143
144 // Задача размеров и позиции окна
145 glutInitWindowPosition(0, 0);
146 glutInitWindowSize(500, 500);
147 // Создание окна
148 glutCreateWindow("T05GRAPH");
149
150 // Установка функций 'обратного вызова'
151 glutDisplayFunc(Display);
152 glutKeyboardFunc(Keyboard);
153
154 // Запускаем основной цикл построения
155 glutMainLoop();
156 return 0;
157 } /* End of 'main' function */
158
159 /* END OF 'T05GRAPH.CPP' FILE */
"GRAPH.CPP"
1 /* FILENAME: GRAPH.CPP
2 * LAST UPDATE: 17.01.2016
3 */
4
5 #include "GRAPH.H"
6
7 /* Load Array of points function */
8 // Загрузка графика из файла по точкам
9 void graph::LoadArray( char *FileName )
10 {
11 // Создание указателя на тип FILE
12 FILE *F;
13
14 // Создание файла и открытие его в режиме чтения
15 fopen_s(&F, FileName, "rt");
16
17 // Количество точек
18 fscanf(F, "%d", &N);
19 // Шаг функции
20 fscanf(F, "%lf", &Step);
21 // Начальная координата по X
22 fscanf(F, "%lf", &MinX);
23 // Конечная координата по X
24 fscanf(F, "%lf", &MaxX);
25
26 // Выделение памяти под массив точек
27 mas = new vec[N];
28
29 // Заполнение массива точек из файла
30 for (int i = 0; i < N; ++i)
31 {
32 // Заполнение по X
33 fscanf(F, "%lf", &mas[i].X);
34 // Заполнение по Y
35 fscanf(F, "%lf", &mas[i].Y);
36 }
37
38 // Закрытие файла
39 fclose(F);
40 } /* End of 'LoadArray' function */
41
42 /* Fill mas function */
43 // Заполнение массива координат точек с цветом
44 void graph::Fill( double(*f)(double) )
45 {
46 // Выделение памяти под массив точек
47 mas = new vec[N];
48 // Выделение памяти под массив цветов
49 Color = new vec[N];
50
51 // Заполнение массивов
52 for (int i = 0; i < N; i++)
53 {
54 mas[i] = vec(MinX + i * Step, f(MinX + i * Step));
55 Color[i] = vec::Rnd();
56 }
57 } /* End of 'Fill' function */
58
59 /* Draw graph function */
60 // Рисование заполненного графика на экран
61 void graph::Draw( void )
62 {
63 // Задача размер точки
64 glPointSize(1);
65 // Рисование
66 glBegin(GL_POINTS);
67 for (int i = 0; i < N; i++)
68 glVertex2d(mas[i].X, mas[i].Y);
69 glEnd();
70 } /* End of 'Draw' function */
71
72 /* Draw graph function */
73 // Рисование не заполненного еще графика на экран
74 void graph::Draw( double(*f)(double) )
75 {
76 // Заполнение массива
77 graph::Fill(f);
78
79 // Задача цвета и размера точки
80 glColor3d(0, 0, 0);
81 glPointSize(1);
82 // Рисование
83 glBegin(GL_POINTS);
84 for (int i = 0; i < N; i++)
85 glVertex2d(mas[i].X, mas[i].Y);
86 glEnd();
87 } /* End of 'Draw' function */
88
89 /* Interpolation draw graph function */
90 // Рисование интерполированного графика на экран
91 void graph::Interpolation_Draw( double i_step )
92 {
93 // Коэффициент Катмулл-Рома
94 double alpha = 1.0 / 6;
95
96 // Кубическая интерполяция кривыми Безье
97 for (int i = 0; i < N - 1; i++)
98 {
99 // Создание 4 точек для интерполяции по ним
100 vec P0 = mas[i], P1, P2, P3 = mas[i + 1];
101 vec Color0 = mas[i], Color1, Color2, Color3 = mas[i + 1];
102
103 // Значения для первого и последнего отрезков
104 if (i == 0)
105 {
106 P1 = (mas[1] - mas[0]) * alpha + mas[0];
107 Color1 = (mas[1] - mas[0]) * alpha + mas[0];
108 }
109 else
110 {
111 P1 = (mas[i + 1] - mas[i - 1]) * alpha + mas[i];
112 Color1 = (mas[i + 1] - mas[i - 1]) * alpha + mas[i];
113 }
114 if (i == N - 2)
115 {
116 P2 = -(mas[N - 1] - mas[N - 2]) * alpha + mas[N - 1];
117 Color2 = -(mas[N - 1] - mas[N - 2]) * alpha + mas[N - 1];
118 }
119 else
120 {
121 P2 = -(mas[i + 2] - mas[i]) * alpha + mas[i + 1];
122 Color2 = -(mas[i + 2] - mas[i]) * alpha + mas[i + 1];
123 }
124
125 glLineWidth(2);
126 glBegin(GL_LINE_STRIP);
127 for (double t = 0; t <= 1; t += i_step)
128 {
129 vec p, color;
130
131 // Вычисление точки интерполированного графика по 4 точкам
132 p = P0 * (1 - t) * (1 - t) * (1 - t) + P1 * 3 * (1 - t) * (1 - t) * t + P2 * 3 * (1 - t) * t * t + P3 * t * t * t;
133 color = Color0 * (1 - t) * (1 - t) * (1 - t) + Color1 * 3 * (1 - t) * (1 - t) * t + Color2 * 3 * (1 - t) * t * t + Color3 * t * t * t;
134
135 // Рисование
136 glColor3d(color.X / 10, 0, color.Y);
137 glVertex2d(p.X, p.Y);
138 }
139 glEnd();
140 }
141 } /* End of 'Interpolation_Draw' function */
142
143 /* Interpolation graph function */
144 // Интерполяция графика
145 graph graph::Interpolation( double i_step )
146 {
147 graph G_New;
148 // Коэффициент Катмулл-Рома
149 double alpha = 1.0 / 6;
150
151 // Заполнение параметров для нового графика
152 G_New.MinX = MinX;
153 G_New.MaxX = MaxX;
154 G_New.Step = Step * i_step;
155 G_New.N = (int)((G_New.MaxX - G_New.MinX) / G_New.Step);
156 G_New.mas = new vec[G_New.N];
157
158 // Кубическая интерполяция кривыми Безье
159 for (int i = 0; i < N - 1; i++)
160 {
161 // Создание 4 точек для интерполяции по ним
162 vec P0 = mas[i], P1, P2, P3 = mas[i + 1];
163
164 // Значения для первого и последнего отрезков
165 if (i == 0)
166 P1 = (mas[1] - mas[0]) * alpha + mas[0];
167 else
168 P1 = (mas[i + 1] - mas[i - 1]) * alpha + mas[i];
169 if (i == N - 2)
170 P2 = -(mas[N - 1] - mas[N - 2]) * alpha + mas[N - 1];
171 else
172 P2 = -(mas[i + 2] - mas[i]) * alpha + mas[i + 1];
173
174 for (double t = 0; t <= 1; t += i_step)
175 {
176 vec p;
177
178 // Вычисление точки интерполированного графика по 4 точкам
179 G_New.mas[(int)((t + i) / i_step)] = P0 * (1 - t) * (1 - t) * (1 - t) + P1 * 3 * (1 - t) * (1 - t) * t + P2 * 3 * (1 - t) * t * t + P3 * t * t * t;
180 }
181 }
182
183 return G_New;
184 } /* End of 'Interpolation' function */
185
186 /* Sum of 2 graphics function */
187 // Сложение двух графиков
188 graph graph::operator+( graph &G )
189 {
190 graph G_New, G1, G2;
191 int i, j;
192
193 // Заполнение параметров графика суммы
194 G_New.MinX = (MinX >= G.MinX) ? MinX : G.MinX;
195 G_New.MaxX = (MaxX <= G.MaxX) ? MaxX : G.MaxX;
196 G_New.Step = Step * G.Step;
197 G_New.N = (int)((G_New.MaxX - G_New.MinX) / G_New.Step);
198 G_New.mas = new vec[G_New.N];
199
200 // Интерполяция слагаемых графиков, для приведение к общему шагу
201 G1 = Interpolation(G.Step);
202 G2 = G.Interpolation(Step);
203
204 // Поиск общего начала и конца графиков
205 for (i = 0; i < G1.N; i++)
206 if (fabs(G1.mas[i].X - G_New.MinX) <= Threshold)
207 break;
208
209 for (j = 0; j < G2.N; j++)
210 if (fabs(G2.mas[j].X - G_New.MinX) <= Threshold)
211 break;
212
213 // Заполнение графика суммы
214 for (int k = 0; k < G_New.N; k++)
215 {
216 G_New.mas[k].X = G_New.MinX + k * G_New.Step;
217 G_New.mas[k].Y = G1.mas[i + k].Y + G2.mas[j + k].Y;
218 }
219
220 return G_New;
221 } /* End of 'Sum' function */
222
223 /* Save Array of points function */
224 // Сохранение графика в файл по точкам
225 void graph::SaveArray( void )
226 {
227 // Создание указателя на тип FILE
228 FILE *F;
229
230 // Создание файла и открытие его в режиме записи
231 fopen_s(&F, "graph.txt", "wt");
232
233 /* Запись в файл данных */
234 // Количество точек
235 fprintf(F, "%d\n", N);
236 // Шаг функции
237 fprintf(F, "%lf\n", Step);
238 // Начальная координата по X
239 fprintf(F, "%lf\n", MinX);
240 // Конечная координата по X
241 fprintf(F, "%lf\n", MaxX);
242
243 // Координаты всех точек
244 for (int i = 0; i < N; ++i)
245 fprintf(F, "%lf %lf ", mas[i].X, mas[i].Y);
246
247 // Закрытие файла
248 fclose(F);
249 } /* End of 'SaveArray' function */
250
251 /* Approximation of function function */
252 // Аппроксимация графика
253 void graph::Approximation( void )
254 {
255 double k, b, s1 = 0, s2 = 0, s3 = 0, s4 = 0;
256
257 // Линейная аппроксимация
258 for (int i = 0; i < N; i++)
259 {
260 if (fabs(mas[i].X) < MAX && fabs(mas[i].Y) < MAX)
261 {
262 s1 += mas[i].X * mas[i].Y;
263 s2 += mas[i].X;
264 s3 += mas[i].X * mas[i].X;
265 s4 += mas[i].Y;
266 }
267 }
268
269 k = (N * s1 - s2 * s4) / (double(N) * s3 - s2 * s2);
270 b = (s4 - k * s2) / double(N);
271
272 // Задача цвета и ширины линии
273 glColor3d(1, 0.5, 0);
274 glLineWidth(1);
275 // Рисование
276 glBegin(GL_LINE_STRIP);
277 glVertex2d(MinX, MinX * k + b);
278 glVertex2d(MaxX, MaxX * k + b);
279 glEnd();
280 } /* End of 'Approximation' function */
281
282 /* End of 'GRAPH.CPP' file */
"GRAPH.H"
1 /* FILENAME: GRAPH.H
2 * LAST UPDATE: 17.01.2016
3 */
4
5 #ifndef _GRAPH_H_
6 #define _GRAPH_H_
7
8 #define _CRT_SECURE_NO_WARNINGS
9
10 #include <iostream>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <time.h>
15 #include <GL\glut.h>
16
17 #define MAX 100
18
19 using namespace std;
20
21 /* Useful constants */
22 const double Threshold = 1e-10;
23 const double Infinity = 1e+10;
24
25 /* Vector representation type */
26 class vec
27 {
28 public:
29 double X, Y;
30
31 /* Default constructor */
32 vec( void )
33 {
34 }
35
36 /* Class constructor */
37 vec( double A ) : X(A), Y(A)
38 {
39 }
40
41 /* Class constructor */
42 vec( double A, double B ) : X(A), Y(B)
43 {
44 }
45
46 static double R0( void )
47 {
48 return rand() / (double)RAND_MAX;
49 } /* End of 'R0' function */
50
51 static vec Rnd( void )
52 {
53 return vec(R0(), R0());
54 } /* End of 'Rnd' function */
55
56 /* The functions of operations on vectors */
57
58 /* Vector = vector function */
59 vec operator=( vec &B )
60 {
61 X = B.X;
62 Y = B.Y;
63
64 return B;
65 } /* end of 'operator+' function */
66
67 /* Vector add vector function */
68 vec operator+( const vec &B ) const
69 {
70 return vec(X + B.X, Y + B.Y);
71 } /* end of 'operator+' function */
72
73 /* Vector sub vector function */
74 vec operator-( const vec &B ) const
75 {
76 return vec(X - B.X, Y - B.Y);
77 } /* end of 'operator-' function */
78
79 vec operator-( void ) const
80 {
81 return vec(-X, -Y);
82 } /* end of 'operator-' function */
83
84 /* Vector mul number function */
85 vec operator*( const double N ) const
86 {
87 return vec(X * N, Y * N);
88 } /* end of 'operator*' function */
89
90 /* Vector div number function */
91 vec operator/( const double N ) const
92 {
93 return vec(X / N, Y / N);
94 } /* end of 'operator/' function */
95
96 /* Vector dot vector function */
97 double operator&( const vec &B ) const
98 {
99 return double(X * B.X + Y * B.Y);
100 } /* end of 'operator&' function */
101
102 vec & operator+=( const vec &B )
103 {
104 X += B.X;
105 Y += B.Y;
106
107 return *this;
108 } /* end of 'operator+=' function */
109
110 vec & operator-=( const vec &B )
111 {
112 X -= B.X;
113 Y -= B.Y;
114
115 return *this;
116 } /* end of 'operator-=' function */
117
118 vec & operator*=( const double N )
119 {
120 X *= N;
121 Y *= N;
122
123 return *this;
124 } /* end of 'operator*=' function */
125
126 vec & operator/=( const double N )
127 {
128 X /= N;
129 Y /= N;
130
131 return *this;
132 } /* end of 'operator/=' function */
133
134 double operator!( void ) const
135 {
136 return double(X * X + Y * Y);
137 } /* end of 'operator!' function */
138
139 /* Access vector components by index function */
140 double operator[]( const int i ) const
141 {
142 switch (i)
143 {
144 case 0:
145 return double(X);
146 case 1:
147 return double(Y);
148 }
149 } /* end of 'operator[]' function */
150
151 /* Normalizing vector function */
152 vec & Normalize( void )
153 {
154 double len = !*this;
155
156 if (len != 1 && len != 0)
157 *this /= sqrt(len);
158 return *this;
159 } /* end of 'Normalize' function */
160 }; /* end of 'vec' class */
161
162 /* Graph class */
163 class graph
164 {
165 public:
166 double MinX, MaxX, Step; // Начальная координата по X; Конечная координата по X; Шаг функции
167 int N; // Количество точек
168 vec *mas, *Color; // Массивы точек и цветов
169
170 /* Default constructor */
171 graph( void )
172 {
173 MinX = -10, MaxX = 10, Step = 0.1, N = 200;
174 }
175
176 /* Class constructor */
177 graph( double _MinX, double _MaxX, double _Step ) : MinX(_MinX), MaxX(_MaxX), Step(_Step)
178 {
179 N = (int)((MaxX - MinX) / Step);
180 // Выделение памяти
181 mas = new vec[N];
182 Color = new vec[N];
183 }
184
185 /* Load Array of points function */
186 void LoadArray( char *FileName );
187
188 /* Fill mas function */
189 void Fill( double(*f)(double) );
190
191 /* Draw graph function */
192 void Draw( double(*f)(double) );
193
194 /* Draw graph function */
195 void Draw( void );
196
197 /* Interpolation draw graph function */
198 void Interpolation_Draw( double i_step );
199
200 /* Interpolation graph function */
201 graph Interpolation( double i_step );
202
203 /* Sum of 2 graphics function */
204 graph operator+( graph &G );
205
206 /* Save Array of points function */
207 void SaveArray( void );
208
209 /* Approximation of function function */
210 void Approximation( void );
211 }; /* end of 'graph' class */
212
213 #endif /* _GRAPH_H_ */
214
215 /* End of 'GRAPH.H' file */
Алгоритм: функции хранятся в программе как массив точек, заданных с определённым шагом по X на заданном отрезке. Вводить значения функции в программу можно двумя способами: с помощью математических функций из стандартных библиотек, указывая начало и конец отрезка, а также шаг, с которым определена функция, и считывая координаты точек из файла, предварительно считав их количество. Далее с любыми функциями можно производить следующие действия и их комбинации: сложение, вычитание, кубическая интерполяция и линейная аппроксимация. При этом результат каждого из этих действий - новая функция, с которой можно продолжать работу. Функции можно выводить на экран с помощью средств графической библиотеки OpenGL, а также печатать её значения в файл.
Инструкция: пользователь вводит необходимые действия с функциями в функции Display. На данный момент при запуске программы можно увидеть пример её работы: первая функция считывается из файла, интерполируется и выводится на экран. Затем вторая функция вводится из библиотеки math.h интерполируется и выводится на экран. Затем функции суммируются, интерполируются и выводятся на экран. File:Func_Abramov.rar
Ссылка на скачивание: [2]
Описание программы: Программа считывает из файла значения функций и количество точек, затем с ними можно провести следующие действия: сложить, умножить, линейно интерполировать и линейно аппроксимировать. Все результаты выводятся в отдельные файлы.
Пояснения к работе: В два текстовые файла занести количество точек и значения абсцисс и ординат функций, который написать в первом и втором пунктах меню, затем выбрать необходимую операцию и ввести имя файла, в который сохранятся полученные значения.
Скачать можно тут.
Краткое описание алгоритма: в классе создаются две различные функции, а также функции для осуществления арифметических операций - сложения, вычитания, умножения и деления. Кроме того, созданы функции интерполяции и аппроксимации результата. Все результаты записываются в файлы, названия которых выводятся на экран в процессе работы программы.
Инструкция к программе: при запуске программа предлагает ввести начало интервала, его конец и шаг для обеих функций. Далее пользователь выбирает одну из предложенных арифметических операций - сложение, вычитание, умножение или деление. После проведения вычислений программа предлагает пользователю интерполировать и аппроксимировать результат выбранной арифметической операции. Пользователь может давать команды на выполнение арифметических операций неограниченное число раз, программа завершает работу по команде пользователя.
Скачать программу можно здесь: [3].
1 #include <iostream> ///программа, перегружающая операторы для работы с двумя функциями,
2 #include <fstream> ///интерполирующая и аппроксимирующая результат арифметических операций над этими функциями
3 #include <math.h>
4
5 using namespace std;
6
7 class functions ///класс, хранящий значения введенных пользователем значений начала и конца исследуемого интервала, а также шага функции
8 {
9 private:
10 double *massiv1, *massiv2, *massiv3; ///указатели на массивы, которые будут использованы в программе
11 ///massiv1 - массив, хранящий изначальные значения функций, massiv2 - массив, хранящий значения одной из функций после интерполяции
12 ///massiv3 - массив, хранящий значения суммы/разности/умножения/деления функций
13 double quantity_before_interpolation, Begin, End, Step;
14 ///quantity - количество элементов в массиве(переменная типа double), Begin и End - начало и конец рассматриваемого отрезка, Step - шаг функции
15
16 public:
17
18 int amount_before_interpolation; ///amount - количество элементов в массиве (переменная типа int)
19 functions (double Begin1, double End1, double Step1 ):Begin(Begin1), End(End1), Step(Step1) ///переменные, в которые закладываются значения, введенные пользоватедем
20 {
21 quantity_before_interpolation =((End-Begin)/Step) + 1; ///расчёт количества элементов в массиве
22 amount_before_interpolation = static_cast < int >(quantity_before_interpolation); ///перевод значения количества элементов из типа double в тип int
23 }
24
25 void function1(double Begin, double End, double Step) ///задание первой функции
26 {
27 massiv1 = new double [amount_before_interpolation]; ///создание массива для хранения значений функций
28 ofstream out ("Function1.txt"); ///запись в файл значений первой функции
29 out << "The size of the range = " << amount_before_interpolation << '\n' << endl;; ///вывод на экран количества элементов данного массива
30 for (int i = 0; i < amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
31 {
32 massiv1[i] = 2*i*Step+Begin; ///формула вычисления
33 out << "y(x=" << i << ")= " << massiv1[i] << endl; ///вывод на экран полученных значений
34 }
35 out.close(); ///завершение записи в файл
36 }
37
38 void function2(double Begin,double End,double Step) ///задание второй функции
39 {
40 massiv1 = new double [amount_before_interpolation]; ///создание массива для хранения значений функции
41 ofstream out ("Function2.txt"); ///запись в файл значений второй функции
42 out << "The size of the range = " << amount_before_interpolation << '\n' << endl;; ///вывод на экран количества элементов данного массива
43 for (int i = 0; i < amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
44 {
45 massiv1[i] = i*Step; ///формула вычисления
46 out << "y(x=" << i << ")= " << massiv1[i] << endl; ///вывод на экран полученных значений
47 }
48 out.close(); ///завершение записи в файл
49 }
50
51 void interpolation (double Begin1, double End1, double Step2) ///интерполяция результата по новому шагу
52 {
53 ofstream out ("Interpolation.txt"); ///запись в файл интерполированных значений функции
54 double quantity_after_interpolation =((End1-Begin1)/Step2) + 1; ///расчёт количества элементов в массиве
55 int amount_after_interpolation = static_cast < int > (quantity_after_interpolation); ///перевод значения количества элементов из типа double в тип int
56 out << "After interpolation the size of range = " << amount_after_interpolation << '\n' << endl;
57
58 massiv3 = new double [amount_after_interpolation]; ///создание массива для хранения значений функции
59 for (int i = 0; i < amount_after_interpolation; ++i) ///цикл, вычисляющий значения функции
60 {
61 double x = i*Step2 + Begin1; ///расчёт х-вой координаты
62 double x0 = static_cast < int >((x - Begin1)/Step + Begin1); ///расчёт нулевой х-вой координаты
63 ///перевод значения х0 из типа double в тип int
64 ///расчёт х-вой координаты, считая от введенного значения начала интервала
65 double x1 = x0 + Step; ///расчёт следующего значения х-вой координаты
66 int i_0 = (x - Begin1)/Step; ///расчёт нулевого индекса
67 int i0 = static_cast < int > (i_0); ///перевод нулевого индекса из типа double в тип int
68 int i1 = i0 + 1; ///расчёт следующего индекса
69 massiv3[i]=(((x - x0)*(massiv2[i1] - massiv2[i0]))/(x1-x0)) + massiv2[i0]; ///формула вычисления
70 out << "y(x=" << i << ")= " << massiv2[i] << endl; ///вывод на экран полученных значений
71 }
72 out.close(); ///завершение записи в файл
73 }
74
75 void approximation(double Begin1, double End1, double Step2) ///функция, аппроксимирующая результат сложения/вычитания/умножения/деления функций
76 {
77 amount_before_interpolation=(End1-Begin1)/Step2+1;
78 int SIZE = static_cast <int> (amount_before_interpolation); /// для удобства вводим переменную SIZE и закладываем в нее значение размера массива
79
80 ///обнуление переменных
81 double sumX = 0; ///переменная, хранящая значение суммы х-вых координат
82 double sumY = 0; ///переменная, хранящая значение суммы у-вых координат
83 double sumXY = 0; ///переменная, хранящая значение суммы произведений х-вой и у-вой координат
84 double sumX2 = 0; ///переменная, хранящая значение суммы х-вых координат, взятых в квадрате
85 double k=0; ///переменная, хранящая значения углового коэффициента касательной к графику данной функции
86 double b=0; ///переменная, хранящая значение свободного коэффициента
87 double d;
88
89 ofstream out ("Approximation.txt"); ///запись в файл аппроксимированных значений
90 for (int i = 0; i < SIZE; ++i) ///цикл для расчёта сумм, указанных выше
91 {
92 d=i*Step2+Begin1; ///расчёт х-вой координаты
93
94 sumX = d + sumX; ///расчёт суммы х-вых координат
95
96 sumY = massiv3[i] + sumY; ///расчёт суммы у-вых координат
97
98 sumXY = d*massiv3[i] + sumXY; ///расчёт суммы произведений х-вой и у-вой координат
99
100 sumX2 = d*d + sumX2; ///расчёт суммы х-вых координат, взятых в квадрате
101 }
102
103 k =(SIZE*sumXY - sumX*sumY)/(SIZE*sumX2- sumX*sumX); ///расчёт углового коэффициента
104
105 b =(sumY - k*sumX)/SIZE; ///расчёт свободного коэффициента
106
107 out << "The equation, which is got as a result of approximation" << endl; ///вывод уравнения на экран
108
109 if (b > 0) ///вывод уравнения при положительном свободном коэффициенте
110 {
111 out << "y = " << k << "*x+" << b << endl;
112 }
113
114 else if (b < 0) ///вывод уравнения при отрицательном свободном коэффициенте
115 {
116 out << "y = " << k <<"*x" << b << endl;
117 }
118 out.close(); ///завершение записи в файл
119 }
120
121 ///перегрузка операторов
122
123 functions operator+ (functions func3) ///сумма двух функций
124 {
125 massiv2=new double[amount_before_interpolation]; ///создание массива для хранения значений функций
126
127 ofstream out ("Results_of_sum.txt"); ///запись в файл значений после суммирования значений функций
128 out << "sum of the functions" << '\n' << endl;
129
130 for (int i=0; i<amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
131 {
132 massiv2[i] = massiv1[i] + func3.massiv1[i]; ///формула вычисления
133 out << "y (x=" << i << ") = " << massiv2[i] << "\n"; ///вывод на экран полученных значений
134 }
135 out.close(); ///завершение записи в файл
136
137 char d; ///переменная для команды интерполировать результат
138 cout << '\n' << "If you want to interpolate the results, input +, in not, input -" << endl;
139 cin >> d;
140
141 if (d=='+') ///если команда для интерполяции дана
142 {
143 double Step2; ///переменная, хранящая значение нового шага
144 cout << '\n' << "Input the step for interpolation" << endl;
145 cin >> Step2;
146 interpolation(Begin, End, Step2); ///вызов функции и интерполяция результата
147
148 char w; /// переменная для команды аппроксимировать результат
149 cout << '\n' << "If you want to approximate the results, input +, in not, input -" << endl;
150 cin >> w;
151
152 if (w=='+') ///если команда на аппроксимацию дана
153 {
154 approximation(Begin, End, Step2); ///вызов функции и аппроксимация результата
155 }
156 }
157 }
158
159 functions operator- (functions func3) ///разность двух функций
160 {
161 massiv2=new double[amount_before_interpolation]; ///создание массива для хранения значений функций
162
163 ofstream out ("Results_of_difference.txt"); ///запись в файл значений второй функции
164 out << "difference of the functions" << '\n' << endl;
165
166 for (int i=0; i<amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
167 {
168 massiv2[i] = massiv1[i] - func3.massiv1[i]; ///формула вычисления
169 out << "y (x=" << i << ") = " << massiv2[i] << "\n"; ///вывод на экран полученных значений
170 }
171 out.close(); ///завершение записи в файл
172
173 char d; ///переменная для команды интерполировать результат
174 cout << '\n' << "If you want to interpolate the results, input +, in not, input -" << endl;
175 cin >> d;
176
177 if (d=='+') ///если команда для интерполяции дана
178 {
179 double Step2; ///переменная, хранящая значение нового шага
180 cout << '\n' << "Input the step for interpolation" << endl;
181 cin >> Step2;
182 interpolation(Begin, End, Step2); ///вызов функции и интерполяция результата
183
184 char w; /// переменная для команды аппроксимировать результат
185 cout << '\n' << "If you want to approximate the results, input +, in not, input -" << endl;
186 cin >> w;
187
188 if (w=='+') ///если команда на аппроксимацию дана
189 {
190 approximation(Begin, End, Step2); ///вызов функции и аппроксимация результата
191 }
192 }
193 }
194
195 functions operator* (functions func3) ///произведение двух функций
196 {
197 massiv2=new double[amount_before_interpolation]; ///создание массива для хранения значений функций
198
199 ofstream out ("Results_of_multiplying.txt"); ///запись в файл значений второй функции
200 out << "multiplying of the functions" << '\n' << endl;
201
202 for (int i=0; i<amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
203 {
204 massiv2[i] = massiv1[i] * func3.massiv1[i]; ///формула вычисления
205 out << "y (x=" << i << ") = " << massiv2[i] << "\n"; ///вывод на экран полученных значений
206 }
207 out.close(); ///завершение записи в файл
208
209 char d; ///переменная для команды интерполировать результат
210 cout << '\n' << "If you want to interpolate the results, input +, in not, input -" << endl;
211 cin >> d;
212
213 if (d=='+') ///если команда для интерполяции дана
214 {
215 double Step2; ///переменная, хранящая значение нового шага
216 cout << '\n' << "Input the step for interpolation" << endl;
217 cin >> Step2;
218 interpolation(Begin, End, Step2); ///вызов функции и интерполяция результата
219
220 char w; /// переменная для команды аппроксимировать результат
221 cout << '\n' << "If you want to approximate the results, input +, in not, input -" << endl;
222 cin >> w;
223
224 if (w=='+') ///если команда на аппроксимацию дана
225 {
226 approximation(Begin, End, Step2); ///вызов функции и аппроксимация результата
227 }
228 }
229 }
230
231 functions operator/ (functions func3) ///деление двух функций
232 {
233 massiv2=new double[amount_before_interpolation]; ///создание массива для хранения значений функций
234
235 ofstream out ("Results_of_dividing.txt"); ///запись в файл значений после деления значения первой функции на значения второй функции
236 out << "dividing of the functions" << '\n' << endl;
237
238 for (int i=0; i<amount_before_interpolation; ++i) ///цикл, вычисляющий значения функции
239 {
240 massiv2[i] = massiv1[i] / func3.massiv1[i]; ///формула вычисления
241 out << "y (x=" << i << ") = " << massiv2[i] << "\n"; ///вывод на экран полученных значений
242 }
243 out.close(); ///завершение записи в файл
244
245 char d; ///переменная для команды интерполировать результат
246 cout << '\n' << "If you want to interpolate the results, input +, in not, input -" << endl;
247 cin >> d;
248
249 if (d=='+') ///если команда для интерполяции дана
250 {
251 double Step2; ///переменная, хранящая значение нового шага
252 cout << '\n' << "Input the step for interpolation" << endl;
253 cin >> Step2;
254 interpolation(Begin, End, Step2); ///вызов функции и интерполяция результата
255
256 char w; /// переменная для команды аппроксимировать результат
257 cout << '\n' << "If you want to approximate the results, input +, in not, input -" << endl;
258 cin >> w;
259
260 if (w=='+') ///если команда на аппроксимацию дана
261 {
262 approximation(Begin, End, Step2); ///вызов функции и аппроксимация результата
263 }
264 }
265 }
266 };
267
268 int main()
269 {
270 double Begin1, End1, Step1; ///переменные, вводимые пользователем
271 cout << "Input the beginning of the interval" << endl; ///ввод начала отрезка
272 cin >> Begin1;
273 cout << '\n' << "Input the end of the interval" << endl; ///ввод конца отрезка
274 cin >> End1;
275 cout << '\n' << "Input the step of functions" << endl; ///ввод начального шага функций
276 cin >> Step1;
277
278 functions func1(Begin1, End1, Step1); ///вызов первой функции
279 func1.function1(Begin1, End1, Step1);
280 cout <<'\n' << "Meanings of the first function are saved in file called 'Function1.txt'" << endl;
281
282 functions func2(Begin1, End1, Step1); ///вызов второй функции
283 func2.function2(Begin1, End1, Step1);
284 cout <<'\n' << "Meanings of the second function are saved in file called 'Function2.txt'" << endl;
285
286 functions func3(Begin1,End1,Step1); ///вызов третьей функции
287
288 char s; ///переменная, используется в цикле
289 do
290 {
291 char c; ///переменная, хранящая выбор арифметической операции пользователем
292 cout << '\n' << "Input your choice: + for sum,- for difference,* for multiplying,/ for dividing" << endl;
293 cin >> c;
294
295 if (c=='+') ///цикл, запускающий функцию расчёта суммы двух функций, их интерполяцию и аппроксимацию
296 {
297 func3=func1+func2; ///формула расчёта суммы
298 cout << '\n' << "Results of sum are saved in file called 'Results_of_sum.txt'" << endl;
299 cout << '\n' << "Result of interpolation is saved in file called 'Interpolation.txt'" << endl;
300 cout << '\n' << "Result of approximation is saved in file called 'Interpolation.txt'" << endl;
301 }
302 if (c=='-') ///цикл, запускающий функцию расчёта разности двух функций, их интерполяцию и аппроксимацию
303 {
304 func3=func1-func2; ///формула расчёта разности
305 cout << '\n' << "Results of difference are saved in file called 'Results_of_difference.txt'" << endl;
306 cout << '\n' << "Result of interpolation is saved in file called 'Interpolation.txt'" << endl;
307 cout << '\n' << "Result of approximation is saved in file called 'Interpolation.txt'" << endl;
308 }
309 if (c=='*') ///цикл, запускающий функцию расчёта произведения двух функций, их интерполяцию и аппроксимацию
310 {
311 func3=func1*func2; ///формула расчёта произведения
312 cout << '\n' << "Results of multiplying are saved in file called 'Results_of_multiplying.txt'" << endl;
313 cout << '\n' << "Result of interpolation is saved in file called 'Interpolation.txt'" << endl;
314 cout << '\n' << "Result of approximation is saved in file called 'Interpolation.txt'" << endl;
315 }
316 if (c=='/') ///цикл, запускающий функцию расчёта частного двух функций, их интерполяцию и аппроксимацию
317 {
318 func3=func1/func2; ///формула расчёта частного
319 cout << '\n' << "Results of dividing are saved in file called 'Results_of_dividing.txt'" << endl;
320 cout << '\n' << "Result of interpolation is saved in file called 'Interpolation.txt'" << endl;
321 cout << '\n' << "Result of approximation is saved in file called 'Interpolation.txt'" << endl;
322 }
323
324 cout << '\n' << "If you want program continue counting, input +, if not, input -" << endl;
325 ///команда пользователя на продолжение работы цикла или же на его завершение
326 cin >> s;
327
328 if (s=='-') ///если дана команда на завершение работы цикла
329 {
330 cout << '\n' << "All results are saved in files." << endl; ///вывод на экран сообщения о записи в файл всех результатов
331 cout << '\n' << "The program is finished." << endl; ///вывод на экран сообщения о завершении работы программы
332 return 0;
333 }
334 }
335 while (s != '-'); ///работа цикла не завершается до тех пор, пока пользователь не даст соответствующую команду
336
337 }
Инструкция к программе:сначала в папке с программой создаются два файла input1 и input2, в которых на первой строчке число точек в функции, а потом в два столбика значения х и у (функции должны быть с одинаковым шагом). Пользователь поочередно выбирает действия: 1 - нужно будет написать имя файла, откуда считывать значения для первой функции (х и у), 2 - для второй функции, 3 - сложение функций, пишем название файла, куда будут записываться значения, 4 - разность, 5 - умножение, 6 - интерполяция функции с шагом 0,5 , получившейся в результате сложения двух начальных,(можно сделать интерполяцию функций, которые получились в результате разности или умножения, но нужно будет в коде в case 6: newf3.Inter(0.5).output() поменять индекс функции и новый шаг), 7 - аппроксимация функции, получившейся в результате сложения двух начальных,(можно сделать аппроксимацию функций, которые получились в результате разности или умножения, но нужно будет в коде в case 7: newf3.Approxy().output() поменять индекс функции), 8 - выход.
Краткое описание алгоритма: функции хранятся в программе как массив точек, заданных с определённым шагом по X на заданном отрезке. Вводить значения функции в программу можно считывая координаты точек из файла. Далее с любыми функциями можно производить следующие действия: сложение, вычитание, умножение, интерполяция и аппроксимация. При этом результат каждого из этих действий - новая функция. Результаты выводятся в файл.
Скачать программу можно по ссылке [4].