functions.h |
#ifndef FUNCTIONS_H_INCLUDED #define FUNCTIONS_H_INCLUDED #include <math.h> typedef struct cal { char c; double r; char s[100]; }; typedef struct per { char name; double zna; };
cal TABLI; per PEREMENS[6]; short SIZE_PERE,SIZE_TABL;
int Length (char *s) //длина строки { int i=0; while (s[i]!='\0') i++; return i; } int pri (char a) //приоритет операции { switch (a) { case '(': return 0; case ')': return 1; case '-': return 2; case '+': return 2; case '/': return 3; case '*': return 3; case '^': return 4; } } void input_func(char *s,char *rez,per a[],short *numb_per) //заменяет оперции на буквы и заполняет массив именапи переменных { int i,j,size,n; for (i=0,j=0; s[i]!='\0';) { if (s[i]=='S') { rez[j++]='s'; i+=3;}//Sin else if (s[i]=='C') { rez[j++]='c'; i+=3;}//Cos else if (s[i]=='t') { rez[j++]='t'; i+=2;}//tg else if (s[i]=='c') { rez[j++]='T'; i+=3;}//ctg else if (s[i]=='A') { if (s[i+3]=='S') { rez[j++]='S'; i+=6;}//ArcSin else if (s[i+3]=='C') { rez[j++]='C'; i+=6;}//ArcCos else if (s[i+3]=='t') { rez[j++]='p'; i+=5;}//Arctg else if (s[i+3]=='c') { rez[j++]='P'; i+=6;}//Arcctg } else if (s[i]=='l') { if (s[i+1]=='n') { rez[j++]='L'; i+=2;}//ln else if (s[i+1]=='g') { rez[j++]='l'; i+=2;}//lg } else if ((s[i]>='U')&&(s[i]<='Z')||(s[i]>='u')&&(s[i]<='z')) { n=0; while ((n<(*numb_per))&&(s[i]!=a[n].name)&&(s[i]!=a[n].name+32)&&(s[i]!=a[n].name-32)) n++; if (n==(*numb_per)) { a[n].name=s[i]; (*numb_per)++; } (rez[j++]=s[i++]); } else (rez[j++]=s[i++]); } rez[j]='\0'; }
double scanf_number (int *start, char *s) //считывает вещественное число без плавающей точки { double d=0,r=0; short p=0;
while ((s[*start]>='0')&&(s[*start]<='9')) d=d*10+s[(*start)++]-'0';
if ((s[*start]==',')||(s[*start]=='.')) { (*start)++; while ((s[*start]>='0')&&(s[*start]<='9')) { r=r*10+s[(*start)++]-'0'; p++; } } return d+r/pow(10.0,p); }
int zapis (cal *z, char *str,int start, int finish) //формирует таблицу переменных и значений { int i,j; char c='0',h,p;
for (i=start, j=0; i<finish; ) { if ((str[i]>='A')&&(str[i]<='Z')||(str[i]>='a')&&(str[i]<='z')) { z[j].c=c++; p=0; z[j].s[p++]=str[i++]; if (str[i]=='(') { h=1; while (h!=0) { z[j].s[p++]=str[i++];
if (str[i]==')') h--; else if (str[i]=='(') h++; } z[j].s[p++]=')'; i++; } z[j].s[p]='\0'; z[j].r=0; } else if ((str[i]=='+')||(str[i]=='-')||(str[i]=='*')||(str[i]=='/')||(str[i]=='^')||(str[i]=='(')||(str[i]==')')) { z[j].c=str[i++]; z[j].r=0; z[j].s[0]='\0'; } else if ((str[i]>='0')&&(str[i]<='9')) { z[j].c=c++; z[j].r=scanf_number(&i,str); z[j].s[0]='\0'; } j++; } return j; }
void cop(cal *b, cal *PS) //копирует таблицу PS в b { int i=0; b->c=PS->c; b->r=PS->r; while (PS->s[i]!='\0') b->s[i]=PS->s[i++]; b->s[i]='\0'; }
int ObratPoleZap (cal *PS,cal *b,int size) //формирует обратную польскую запись { char CPO[40]=""; char ch,j=0,l=0,i=1,t; char n=0,r;
while (n<size) { if ((PS[n].c>='0')&&(PS[n].c<=']')) cop(&b[j++],&PS[n++]); else { if (PS[n].c=='(') CPO[l++]=PS[n++].c; else if (PS[n].c!=')') { if ((l==0)||(pri(CPO[l-1])<pri(PS[n].c))) CPO[l++]=PS[n++].c; else { while ((l!=0)&&(pri(CPO[l-1])>=pri(PS[n].c))&&(CPO[l-1]!='(')) { r=0; while (PS[r].c!=CPO[l-1]) r++; cop(&b[j++],&PS[r]); l--; } CPO[l++]=PS[n++].c; } } else { while (CPO[l-1]!='(') { r=0; while (PS[r].c!=CPO[l-1]) r++; cop(&b[j++],&PS[r]); l--; } l--; n++; } } }
l--; while (l>=0) { r=0; while (PS[r].c!=CPO[l]) r++; cop(&b[j++],&PS[r]); l--; }
return j; } double computing(cal *PS,int size,per a[], short sizeZna) //проводит вычисления по ОПЗ { cal n[100]; cal y[100]; double STAK[10]; int i=0,j,t=0,si,p; double rez; while (i<size) { if ((PS[i].c>='0')&&(PS[i].c<=']')) { if (PS[i].s[0]=='\0') STAK[t++]=PS[i].r; else { if ((PS[i].s[0]=='s')||(PS[i].s[0]=='c')||(PS[i].s[0]=='t')||(PS[i].s[0]=='T')||(PS[i].s[0]=='S')||(PS[i].s[0]=='C')||(PS[i].s[0]=='p')|| (PS[i].s[0]=='P')||(PS[i].s[0]=='L')||(PS[i].s[0]=='l')||(PS[i].s[0]=='e')) { si=zapis(n,PS[i].s,2,Length(PS[i].s)-1); si=ObratPoleZap(n,y,si); rez=computing(y,si,a,sizeZna); switch (PS[i].s[0]) { case 's': {PS[i].r=sin(rez);} break; //Sin case 'c': {PS[i].r=cos(rez);} break; //Cos case 't': {PS[i].r=tan(rez);} break; //tg case 'T': {PS[i].r=1/tan(rez);} break; //ctg case 'S': {PS[i].r=atan(rez/sqrt(1-rez*rez));} break; //ArcSin case 'C': {PS[i].r=2*atan(sqrt((1-rez)/(1+rez)));}break;//ArcCos case 'p': {PS[i].r=atan(rez);} break; //Arctg case 'P': {PS[i].r=3.141592654/2-atan(rez);} break; //Arcctg case 'L': {PS[i].r=log(rez);} break; //ln case 'l': {PS[i].r=log10(rez);} break; //lg case 'e': {PS[i].r=exp(1.);} break; //Exp } STAK[t++]=PS[i].r; } else { p=0; while ((p<sizeZna)&&(a[p].name!=PS[i].s[0])&&(a[p].name+32!=PS[i].s[0])&&(a[p].name-32!=PS[i].s[0])) p++; STAK[t++]=a[p].zna; } } } else { switch (PS[i].c) { case '*': {t-=2; STAK[t]=STAK[t]*STAK[t+1]; t++;} break; case '/': {t-=2; STAK[t]=STAK[t]/STAK[t+1]; t++;} break; case '+': {t-=2; STAK[t]=STAK[t]+STAK[t+1]; t++;} break; case '-': {t-=2; STAK[t]=STAK[t]-STAK[t+1]; t++;} break; case '^': {t-=2; STAK[t]=pow(STAK[t],STAK[t+1]); t++;} break; } } i++; } return STAK[t-1]; } void inp_zna_per (per a[],int size) //заполняем значения переменных { int i; while (i<size) { printf("Enter zna %c :",a[i].name); scanf("%lf",&a[i].zna); i++; } } int input_integr_preob (cal *x, per PEREMEN[],short *size_per) //ввод функции и преобразование в вид для вычислений финкций { char *s, *rez,k; cal z[50];
rez=(char*) malloc (sizeof(char)*100); s=(char*) malloc (sizeof(char)*100); printf("Enter function: "); gets(s); input_func(s,rez,PEREMEN,size_per); k=zapis (z, rez,0,Length(rez)); k=ObratPoleZap (z,x,k); return k; }
void input_integr_func () //ввод функции и преобразование в вид для вычислений финкций F(X) { char *s, *rez; cal z[50];
rez=(char*) malloc (sizeof(char)*100); s=(char*) malloc (sizeof(char)*100); printf("Enter function: "); gets(s); input_func(s,rez,PEREMENS,&SIZE_PERE); SIZE_TABL=zapis (z, rez,0,Length(rez)); SIZE_TABL=ObratPoleZap (z,&TABLI,SIZE_TABL); }
double functio (double y) //возращает значение функции { PEREMENS[0].zna=y; return computing(&TABLI,SIZE_TABL,PEREMENS,1); }
#endif // FUNCTIONS_H_INCLUDED |
integration.h |
#ifndef INTEGRATION_H_INCLUDED #define INTEGRATION_H_INCLUDED #include "functions.h" double centr_rect(double(*F)(double), double e, double a, double b) //метод центральных прямоугольников, использующий принцип Рунге оценки погрешности { int n=2,i,step=0; double h,x,S1, S2;
if (b==a) return 0; else if (b<a) { h=b; b=a; a=h; } e*=3; for (S2=0, i=0, h=(b-a)/n, x=a+h/2; i<n; i++, x+=h) S2+=F(x); S2*=h; do { S1=S2; h=h/2; n+=n; for (S2=0, i=0, x=a+h/2; i<n; i++, x+=h) S2+=F(x); S2*=h; step++; } while ((fabs(S1-S2)>=e)&&(step<100)); if (step<100) return S2; else { printf("Error, input other Epsilon: "); return -1; } }
double trapez(double(*F)(double), double e, double a, double b) //метод трапеций, использующий принцип Рунге оценки погрешности { int n=2,i,step=0; double h,x,S1,S2,medium;
if (b == a) return 0; else if (b<a) { h=b; b=a; a=h; } e*=3; S2=medium=(F(a)+F(b))/2; for (i=1, h=(b-a)/n, x=a; i<n; i++, x+=h) S2+=F(x); S2*=h; do { S1=S2; S2=medium; n+=n; for (i=1, h=h/2, x=a; i<n; i++, x+=h) S2+=F(x); S2*=h; step++; } while ((fabs(S1-S2)>=e)&&(step<100)); if (step<100) return S2; else { printf("Error, input other Epsilon: "); return -1; } }
double parabol(double(*F)(double), double e, double a, double b) //метод парабол, использующий принцип Рунге оценки погрешности { int m=1,i,step=0; double h,S1, S2,medium,tmp,tms; if (b==a) return 0; else if (b<a) { h=b; b=a; a=h; } e*=15; S2=medium=(F(a)+F(b))/2; h=(b-a)/(2*m); tmp=0; tms=0; for (i=1; i<m; i++) { tmp+=F(a+h*(2*i-1)); tms+=F(a+h*2*i); } tmp+=F(a+h*(2*i-1)); S2+=4*tmp+2*tms; S2*=h/3; do { S1=S2; S2=medium; m*=2; h=h/2; tmp=0; tms=0; for (i=1; i<m; i++) { tmp+=F(a+h*(2*i-1)); tms+=F(a+h*2*i); } tmp+=F(a+h*(2*i-1)); S2+=4*tmp+2*tms; S2*=h/3; step++; } while ((fabs(S1-S2)>=e)&&(step<100)); if (step<100) return S2; else { printf("Error, input other Epsilon: "); return -1; } } double Gauss(double(*F)(double), double e, double a, double b) //метод Гаусса { short i; double S,ex1,ex2; //таблицы квадратурных коофициентов Гаусса double T[4][4]= { {0 ,0 ,0 ,0 }, //e=1 {-0.57735027 , 0.57735027,0 ,0 }, //e=2 {-0.77459667 , 0 ,0.77459667 ,0 }, //e=3 {-0.86113631 ,-0.33998104,0.33998104 ,0.86113631 }, //e=4 }; double A[4][4]= { {2 ,0 ,0 ,0 }, //e=1 {1 ,1 ,0 ,0 }, //e=2 {0.55555556 ,0.88888889 ,0.55555556 ,0 }, //e=3 {0.34785484 ,0.65214516 ,0.65214516 ,0.34785484 }, //e=4 }; if (b==a) return 0; else if (b<a) { S=b; b=a; a=S; } ex1=(b+a)/2; ex2=(b-a)/2; S=0; for (i=0; i<=(int)e ;i++) S+=F(ex1+ex2*T[(int)e][i])*A[(int)e][i]; S*=ex2; return S; } #endif // INTEGRATION_H_INCLUDED |
main.c |
// Labs4_Number_Inte.cpp: главный файл проекта.
#include "stdafx.h" #include <iostream> #include <stdio.h> #include "functions.h" #include "integration.h"
using namespace System; using namespace std;
int main(array<System::String ^> ^args) { double (*Methods[4])(double(double), double, double, double)={centr_rect,trapez,parabol,Gauss}; short method; double a,b,e,result;
input_integr_func ();
printf("Enter left lim a: "); scanf("%lf",&a); printf("Enter right lim b: "); scanf("%lf",&b);
printf("Enter method numerical integration"); printf("\nMethod center rectangles=0 \nMethod of trapezes=1 \nMethod of parabols=2 \nGauss Method=3"); printf("\nMethod: "); scanf("%d",&method);
if (method==3) printf("Enter n [0-3]: "); else printf("Enter Epsilon: "); scanf("%lf",&e); result=(Methods[method])(functio,e,a,b); printf("\nResult: %lf\n",result);
system("pause"); return 0; }
|
Федеральное агентство по образованию РФ
Государственное образовательное учреждение высшего профессионального образования
Белгородский Государственный Технологический Университет им. В. Г. Шухова.
Кафедра программного обеспечения вычислительной техники и
автоматизированных систем.
Лабораторная работа №4
Численное интегрирование
Выполнил студент группы ПВ-22
Воробьев Р.В.
Проверила Брусенцева В.С.
Белгород 2011г.
Задания к работе
-
Вычислить «вручную» для соответствующего варианта интегралы
- по формуле средних прямоугольников, используя для оценки точности двойной просчет при n1=8; n2=10;
- по формуле Ньютона-Лейбница и по формуле трапеций с тремя десятичными знаками;
- по формуле Симпсона при n=8. Оценить погрешность результата, составив таблицу конечных разностей.
2. Описать в модуле функции, которые возвращают приближенные значения интегралов от функции f(x) с оценкой точности по принципу Рунге для методов
- центральных прямоугольников
- трапеций
- парабол
3. Описать в модуле функцию для вычисления приближенного значения интеграла от функции f(x) по формуле Гаусса с n=1,2,3,4. Узлы t0 и веса a0 приведены в таблице
4. Составить программу для вычислений приближенных значений интегралов от функций п.1-3 с использованием всех функции описанных в модуле.
Задание:
Спецификации подпрограмм:
Спецификация функции centr_rect:
-
Заголовок: double centr_rect(double(*F)(double), double e, double a, double b)
-
Назначение: возвращает приближенно значение интеграла от функции double(*F)(double) с левым приделом a и правым приделом b, с точностью е, решенный методом центральных прямоугольников.
-
Входные параметры: (*F)(double),e,a,b;
-
Выходных параметров нет.
Спецификация функции trapez:
-
Заголовок: double trapez (double(*F)(double), double e, double a, double b)
-
Назначение: возвращает приближенно значение интеграла от функции double(*F)(double) с левым приделом a и правым приделом b, с точностью е, решенный методом трапеций.
-
Входные параметры: (*F)(double),e,a,b;
-
Выходных параметров нет.
Спецификация функции parabol:
-
Заголовок: double parabol (double(*F)(double), double e, double a, double b)
-
Назначение: возвращает приближенно значение интеграла от функции double(*F)(double) с левым приделом a и правым приделом b, с точностью е, решенный методом парабол.
-
Входные параметры: (*F)(double),e,a,b;
-
Выходных параметров нет.
Спецификация функции Gauss:
-
Заголовок: double Gauss (double(*F)(double), double e, double a, double b)
-
Назначение: возвращает приближенно значение интеграла от функции double(*F)(double) с левым приделом a и правым приделом b, с точностью е, решенный методом Гаусса.
-
Входные параметры: (*F)(double),e,a,b;
-
Выходных параметров нет.