Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Вычисление интеграла по методу правых прямоугольников





Рассмотрим вычисление интеграла по методу правых прямоугольников (функция Vych_Int_rpram).

Организуем иначе и саму процедуру вычисления интеграла. Откажемся от выделения процедуры одноразового вычисления площади в виде отдельной функции Sum и «растворим» эту процедуру в теле функции Vych_Int_rpram,наряду с процедурой двойного пересчета. Оптимизируем процесс вычисления площади. Проанализируйте приведенную ниже функцию и ответьте, за счет чего здесь происходит оптимизация:

 

// функция вычисления интеграла по методу правых прямоугольников
// с элементами оптимизации вычисления суммы

void Vych_Int_rpram(double a,double b,double eps,pfunc pf,double *I, int *k)

{double h, S, S1, sum=(*pf)(b);

int n=1, m=0;

*k=0;

S=sum* (b-a); // очень «грубое» вычисление интеграла для входа в цикл

do

{S1= S;

* k +=1; //количество итераций

n=n*2; h=(b-a)/n; // увеличение количества отрезков разбиения и // уменьшение шага интегрирования

int m=1;

while (m<n )

{sum=sum+(*pf)(b-h*m); // накопление суммы высот

// без повторного вычисления высот в «старых» точках!!!

m=m+2;

}

S=h*sum; // вычисление площади

}while (fabs(S-S1)>eps);

*I=S;

}

Использование одинаковых вызовов функции для вычисления интеграла разными методами и для разных функций

Зададим синоним для описания типа «указатель на функцию, тип возвращаемого значения и сигнатура которойсоответствуюттипу возвращаемого значения и сигнатуре функции вычисления интеграла по заданному методу:

typedef void (*pfunc_metod)(double,double,double, pfunc, double *, int *);

 

Функция main тогда может иметь вид:

// pfunc – синоним типа «указатель на функцию (под интегралом)»

typedef double (*pfunc) (double x);

// pfunc_metod – синоним типа «указатель на функцию-метод»

typedef void (*pfunc_metod)(double,double,double, pfunc, double *, int *);

//прототип функции вычисления интеграла по критерию двойного пересчета



void Vych_Int_lpram(double a, double b, double eps, pfunc pf, double *I, int *k);

//прототип функции вычисления суммы по методу левых прямоугольников

void Vych_Int_rpram(double a,double b,double eps,pfunc pf,double *I, int *k);

//прототип функции вычисления суммы по методу правых прямоугольников

void Sum (double a, double b, double h, pfunc pf, double *S);

double f1 (double); //прототипы функций «под интегралом»

double f2 (double);

 

Int main ()

{ double a, b, eps; //отрезок интегрирования, точность, значение суммы

double Int; //переменная, в которой возвращается значение интеграла

int K_iter; //переменная, в которой возвращается количество итераций

pfunc pf=f1; // инициализация указателя адресом функции f1

pfunc_metod pmet = Vych_Int_lpram;

// инициализация указателя адресом функции Vych_Int_lpram

cout << "Input a, b, eps\n";

cin >> a >> b >> eps;

(*pmet) (a,b,eps,(*pf),&Int,&K_iter); //вызов Vych_Int_lpram для f1

cout << "lpram for f1 =" << Int << " K_iter= "<< K_iter << endl;

 

pf=f2; // присваивание указателю на функцию значения f2

(*pmet) (a,b,eps,(*pf),&Int,&K_iter); //вызов Vych_Int_lpram для f2

cout << "lpram for f2 =" << Int << " K_iter = " << K_iter << endl;

 

pmet =Vych_Int_rpram; // указателю присваивается адрес новой функции-метода

(*pmet)(a, b, eps,(*pf),&Int,&K_iter); //вызов Vych_Int_rpram для f2

cout << "rpram for f2 =" << Int << " K_iter = " << K_iter << endl;

 

pf=f1; // инициализация указателя на функцию значением f1

(*pmet) (a, b, eps,(*pf), &Int, &K_iter); //вызов Vych_Int_rpram для f1

cout << "rpram for f1 =" << Int << " K_iter = " << K_iter << endl;

_getch();

return 0;

}

 

void Vych_Int_lpram(double a, double b, double eps, pfunc pf, double *I, int *k)

{int n=20; //инициализация начального количества разбиений

double h=(b-a)/n; //определение шага интегрирования

double S1=0, S2=0; // переменные для значений сумм с шагом h и с шагом h/2

 

//вызов функции Sum1 c шагом h: в S1 возвращается сумма

Sum (a, b, h, (*pf), &S1); //вызов функции для запуска процесса двойного пересчета

//или Sum (a, b, h, pf, &S1);

*k=0;

do

{ S2= S1;

n *=2; //увеличение количества отрезков разбиения и

h=(b-a)/n; //уменьшение шага интегрирования в 2 раза

//вызов функции Sum1 с шагом h=h/2

Sum (a, b, h, (*pf), &S1); //повторное вычисление суммы в S1

//или Sum (a, b, h, pf, &S1);

*k +=1;

}while (fabs(S1-S2) > eps) ;

*I=S1;

}

 

void Vych_Int_rpram(double a, double b, double eps, pfunc pf, double *I, int *k)

{double h, S, S1, sum=(*pf)(b);

int n=1, m=0;

*k=0;

S=sum* (b-a); // очень «грубое» вычисление интеграла для входа в цикл

do

{S1= S;

* k +=1; //количество итераций

n=n*2; h=(b-a)/n; // увеличение количества отрезков разбиения и // уменьшение шага интегрирования

int m=1;

while (m<n )

{sum=sum+(*pf)(b-h*m); // накопление суммы высот

m=m+2;

}

S=h*sum; // вычисление площади

}while (fabs(S-S1)>eps);

*I=S;

}

 

void Sum(double a, double b, double h, pfunc pf, double *S)

{ double x, sum;

x=a;

sum=0;

while (x<b) {

sum=sum+(*pf)(x); //накопление суммы высот

//или sum=sum+pf(x);

x=x+h;

}

*S=h*sum; //вычисление площади

}

 

Double f1 (double x)

{ return cos(x)/exp(0.333333*log(x));

}

Double f2 (double x)

{return cos(x*x*x)/sqrt(sqrt(x));

}

 

Использование при вычислении интеграла многофайловой компиляции

// integral.h:

// pfunc – синоним типа «указатель на функцию (под интегралом)»

typedef double (*pfunc) (double x);

// pfunc_metod – синоним типа «указатель на функцию-метод»

typedef void (*pfunc_metod)(double, double, double, pfunc, double *, int *);

//прототип функции вычисления интеграла по критерию двойного пересчета

void Vych_Int_lpram(double a,double b,double eps,pfunc pf,double *I, int *k);

//прототип функции вычисления суммы по методу левых прямоугольников

void Vych_Int_rpram(double a,double b,double eps,pfunc pf,double *I,int *k);

//прототип функции вычисления суммы по методу правых прямоугольников

void Sum (double a, double b, double h, pfunc pf, double *S);

double f1 (double); //прототипы подынтегральных функций

double f2 (double);

 

// stdafx.h :

#pragma once

 

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>

#include <tchar.h>

 

// TODO: reference additional headers your program requires here

#include <iostream>

#include <conio.h>

#include <math.h>

#include <iomanip>

#include "integral.h"

using namespace std;

 

// f_int.cpp :

#include "stdafx.h"

 

double f1 (double x)

{ return cos(x)/exp(0.333333*log(x));}

 

double f2 (double x)

{return cos(x*x*x)/sqrt(sqrt(x)); }

 

// f_metod_int.cpp :

#include "stdafx.h"

 

 

int main ()

{ double a, b, eps;

double Int;

int K_iter;

pfunc pf=f1;

pfunc_metod pmet =Vych_Int_lpram;

 

cout << "Input a, b, eps\n";

cin >> a >> b >> eps;

(*pmet) (a, b, eps, pf, &Int, &K_iter); // Vych_Int_lpram для f1

cout << "lpram for f1 =" << Int << " K_iter= "<< K_iter << endl;

 

pf=f2;

(*pmet) (a, b, eps, pf, &Int, &K_iter); // Vych_Int_lpram для f2

cout << "lpram for f2 =" << Int << " K_iter = " << K_iter << endl;

 

pmet =Vych_Int_rpram;

(*pmet) (a, b, eps, pf, &Int, &K_iter); // Vych_Int_rpram для f2

cout << "rpram for f2 =" << Int << " K_iter = " << K_iter << endl;

 

pf=f1;

(*pmet) (a, b, eps, pf, &Int, &K_iter); // Vych_Int_rpram для f1

cout << "rpram for f1 =" << Int << " K_iter = " << K_iter << endl;

_getch();

return 0;

}

 

 

void Vych_Int_lpram(double a, double b, double eps, pfunc pf, double *I, int *k)

{int n=20;

double h=(b-a)/n;

double S1=0, S2=0;

Sum (a, b, h, pf, &S1);

*k=0;

do

{ S2= S1;

n *=2;

h=(b-a)/n;

Sum (a, b, h, (*pf), &S1);

*k +=1;

}while (fabs(S1-S2) > eps) ;

*I=S1;

}

 

void Vych_Int_rpram(double a, double b,double eps, pfunc pf,double *I,int *k)

{double h, S, S1, sum=(*pf)(b);

int n=1, m=0;

*k=0;

S=sum* (b-a);

do

{S1= S;

* k +=1;

n=n*2; h=(b-a)/n;

int m=1;

while (m<n )

{sum=sum+(*pf)(b-h*m);

m=m+2;

}

S=h*sum;

}while (fabs(S-S1)>eps);

*I=S;

}

 

void Sum(double a, double b, double h, pfunc pf, double *S)

{ double x, sum;

x=a;

sum=0;

while (x<b) {

sum=sum+(*pf)(x);

x=x+h;

}

*S=h*sum;

}

 

// stdafx.cpp :

#include "stdafx.h"

 

Результаты работы программы:

Input a, b, eps

1 2 0.00001

lpram for f1 =0.0760611 K_iter= 10

lpram for f2 =-0.0769292 K_iter = 11

rpram for f2 =-0.0769423 K_iter = 16

rpram for f1 =0.0760493 K_iter = 16

Press any key to continue

 









ЧТО ПРОИСХОДИТ ВО ВЗРОСЛОЙ ЖИЗНИ? Если вы все еще «неправильно» связаны с матерью, вы избегаете отделения и независимого взрослого существования...

Что способствует осуществлению желаний? Стопроцентная, непоколебимая уверенность в своем...

Что делает отдел по эксплуатации и сопровождению ИС? Отвечает за сохранность данных (расписания копирования, копирование и пр.)...

Живите по правилу: МАЛО ЛИ ЧТО НА СВЕТЕ СУЩЕСТВУЕТ? Я неслучайно подчеркиваю, что место в голове ограничено, а информации вокруг много, и что ваше право...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2021 zdamsam.ru Размещенные материалы защищены законодательством РФ.