Смекни!
smekni.com

Числові методи (стр. 3 из 4)

Вхідні дані:

n- кількість відрізків розбиття;

H - крок розбиття відрізку [X0; Xn]]

М- вектор моментів кубічного сплайну.

Y- вектор значень функції f(x,y) в точках x[0],x[1],...x[n].

Вихідні дані:

Ak- матриця коефіцієнтів кубічного сплайну.*/

{int i;

for (i=0; i<n; i++)

{Ak[i][0] = Y[i];

Ak[i][1] = (Y[i+1]-Y[i])/h-h/6*(2.*M[i]+M[i+1]);

Ak[i][2] = M[i]/2;

Ak[i][3] = (M[i+1]-M[i])/6*h;}}

void main()

{float Y[nMax+1],d[nMax],M[nMax+1],Ak[nMax][4];

int n,i,j;

n=nMax;

M[0]=0; M[n]=0; //крайові умови

char *strError="&bsol;n Error of file !";

FILE *FileIn,*FileOut,*FileOut2;

FileIn=fopen("data2_2in.txt","r"); // відкриваємо файл для читання

if (FileIn==NULL)

{ cout << " &bsol;"Data2_2in.txt&bsol;": Error open file or file not found !!!&bsol;n";

goto exit; }

FileOut=fopen("data2_2ou.txt","w"); // відкриваємо файл для запису

if (FileOut==NULL)

{ cout << " &bsol;"Data2_2ou.txt&bsol;": Error open file !!!&bsol;n";

goto exit; }

FileOut2=fopen("data2_3in.txt","w"); // відкриваємо файл для запису

if (FileOut2==NULL)

{ cout << " &bsol;"Data2_3in.txt&bsol;": Error open file !!!&bsol;n";

goto exit; }

// читаємо вектор Y

for (i=0; i<=n; i++)

if(fscanf(FileIn,"%f,",&(Y[i]))==NULL)

{ cout << strError; goto exit;};

// обчислюємо вектор d

for (i=1; i<n; i++) d[i-1]=3/(h*h)*(Y[i+1]-2*Y[i]+Y[i-1]);

//fMetodProgonku(n-1,a,b,c,d,M);

fSplain( n,h,Y,M,Ak);

// Вивід результатів в тому числі і для наступного завдання

fprintf(FileOut2,"%d&bsol;n",n); // n - кількість відрізків

// координати точок сітки по Х

for(float xi=x0,i=0; i<n; i++) fprintf(FileOut2,"%2.2f ",xi+h*i);

fprintf(FileOut2,"&bsol;n");

for (i=0; i<n; i++)

{for (j=0; j<4; j++)

{printf("a[%d,%d]= %4.4f ",i,j,Ak[i][j]);

fprintf(FileOut,"a[%d,%d]= %4.4f ",i,j,Ak[i][j]);

fprintf(FileOut2,"%4.4f ",Ak[i][j]);}

cout << endl;

fprintf(FileOut,"&bsol;n");

fprintf(FileOut2,"&bsol;n");}

fclose(FileIn);

fclose(FileOut);

exit: cout << "&bsol;n Press any key ...";

getch();}

Результат роботи програми (" data2_2uo.txt"):

a[0,0]= 1.0000 a[0,1]= 0.5104 a[0,2]= 0.0000 a[0,3]= -0.0104

a[1,0]= 1.0500 a[1,1]= 0.4793 a[1,2]= -0.3107 a[1,3]= 0.0118

a[2,0]= 1.0960 a[2,1]= 0.4525 a[2,2]= 0.0429 a[2,3]= -0.0068

a[3,0]= 1.1410 a[3,1]= 0.4407 a[3,2]= -0.1607 a[3,3]= 0.0054

в) Розіб’ємо відрізок

на
частин.

Складова формула Сімпсона буде мати вигляд:

;

де

- крок розбиття,
– значення функції
в точках сітки.

Замінимо

значеннями кубічних сплайнів із пункту б) цього завдання.

Для оцінки похибки використаємо правило Рунге. Для цього обчислимо наближені значення інтегралу з кроком

(
), а потім з кроком
(
).

За наближене значення інтегралу, обчисленого за формулою Сімпсона з поправкою по Рунге приймемо:

.

//------------------------------------------------------------

// Work2_3.cpp

//------------------------------------------------------------

// "Числові методи"

// Завдання 2

// Обчислення інтегралу методом Сімпсона з використанням кубічного сплайну

#include <stdio.h>

#include <iostream.h>

#include <conio.h>

#include <math.h>

// визначення сплайнового класу

class Tsplain

{public:

int kol; // кількість рівнянь (відрізків розбиття)

float ** Ak; // масив коефіцієнтів

float * Xi; // вектор початків відрізків

float vol(float x); // функція повертає значення сплайну в точці х

Tsplain(int k); // constructor};

Tsplain::Tsplain(int k)

{kol=k;

Xi=new float[kol];

Ak=new float*[kol];

for(int i=0; i<kol; i++) Ak[i]=new float[kol];}

float Tsplain::vol(float x)

{float s=0.;

int i,t;

// шукаємо відрізок t де знаходиться точка х

for (i=0; i<kol; i++) if (x>=Xi[i]) { t=i; break; }

s=Ak[t][0];

for (i=1; i<kol; i++)

s+=Ak[t][i]*pow((x-Xi[t]),i);

return s;}

float fSimps(float down,float up, int n, Tsplain *spl)

/* Функція обчислює інтеграл методом Сімпсона з використанням кубічного сплайну

Вхідні дані:

down,up -границі інтегрування ;

n- число відрізків , на яке розбиваєтьться відрізок інтегрування ;

spl - вказівник на об’єкт класу Tsplain ( кубічний сплайн );

Вихідні дані:

функція повертає знайдене значення інтегралу.*/

{float s=0;

float h=(up-down)/(float)n;

int i;

s=spl->vol(down)+spl->vol(up-h);

for (i=2; i<n; i+=2)

s+=2*(spl->vol(down+i*h));

for (i=1; i<n; i+=2)

s+=4*(spl->vol(down+i*h));

return s*h;}

void main()

{int kol; // кількість рівняннь кубічного сплайну

float down,up;

float I1,I2,I,eps;

int n,i,j;

char *strError="&bsol;n Error of file !";

FILE *FileIn,*FileOut;

FileIn=fopen("data2_3in.txt","r"); // відкриваємо файл для читання

if (FileIn==NULL)

{ cout << " &bsol;"Data2_3in.txt&bsol;": Error open file or file not found !!!&bsol;n";

goto exit; }

FileOut=fopen("data2_3ou.txt","w"); // відкриваємо файл для запису

if (FileOut==NULL)

{ cout << " &bsol;"Data2_3ou.txt&bsol;": Error open file !!!&bsol;n";

goto exit; }

// читаємо kol

if(fscanf(FileIn,"%d,",&kol)==NULL)

{ cout << strError; goto exit;};

Tsplain *sp;

sp=new Tsplain(kol);

// читаємо вектор Xi

for(i=0; i<kol; i++) fscanf(FileIn,"%f,",&(sp->Xi[i]));

// читаємо масив Ak

for (i=0; i<kol; i++)

for (j=0; j<kol; j++) fscanf(FileIn,"%f,",&(sp->Ak[i][j]));

// читаємо n - кількість відрізків розбиття відрізку інтегрування

if(fscanf(FileIn,"%d,",&n)==NULL)

{ cout << strError; goto exit;};

down=sp->Xi[0];

up=sp->Xi[sp->kol-1]+(sp->Xi[sp->kol-1]-sp->Xi[sp->kol-2]);

I1=fSimps(down,up, n, sp);

I2=fSimps(down,up, 2*n, sp);

eps=(I2-I1)/15;

I=I2+eps;

// Вивід результатів

printf("I= %5.5f&bsol;n",I);

printf("EPS= %5.5f&bsol;n",eps);

fprintf(FileOut,"I= %5.5f&bsol;n",I);

fprintf(FileOut,"EPS= %5.5f&bsol;n",eps);

fclose(FileIn);

fclose(FileOut);

exit: cout << "&bsol;n Press any key ...";

getch();}

Результат роботи програми ("data2_3ou.txt")

I= 1.32213

EPS= 0.00004

Завдання 3

Знайти розв’язок системи нелінійних рівнянь

,

Рішення.

Умову завдання перепишемо наступним чином

.

Приймаючи що

і
то коротко систему рівнянь можна записати так

.

Якщо відомо деяке наближення

кореня
системи рівнянь, то поправку
можна знайти рішаючи систему

.

Розкладемо ліву частину рівняння по степеням малого вектору

, обмежуючись лінійними членами

.

=
=
– матриця похідних (матриця Якобі) (
).

Складемо матрицю похідних (матрицю Якобі):

Якщо

, то
,

де

– матриця обернена до матриці Якобі.

Таким чином послідовне наближення кореня можна обчислити за формулою

або

.

Умовою закінчення ітераційного процесу наближення корення вибираємо умову

,

– евклідова відстань між двома послідовними наближеннями ;
– число, що задає мінімальне наближення.

Для рішення систем нелінійних рівнянь за даним алгоритмом призначена програма

Work3.cpp

//------------------------------------------------------------

// Work3.cpp

//------------------------------------------------------------

// "Числові методи"

// Завдання 3

// Розв’язування системи нелінійних рівнянь методом Ньютона

#include <stdio.h>

#include <iostream.h>

#include <conio.h>

#include <math.h>

#include "matrix.h"

const int N=2; // степінь матриці Якобі (кількість рівнянь)

typedef void (*funcJ) (float[N], float[N][N]);

void fJakobi(float X[N],float J[N][N])

// функції , які складають матрицю Гессе

{J[0][0]=cos(X[0]); J[0][1]=cos(X[1]);

J[1][0]=2*X[0]; J[1][1]=-2*X[1]+1;}

typedef void (*funcF) (float[N], float[N]);

void fSist(float X[N],float Y[N])

{Y[0]=sin(X[0])+sin(X[1])-1;

Y[1]=X[0]*X[0]-X[1]*X[1]+X[1];}

//int NelinSist(float X[N], funcJ pJakobi, funcF pSist,float eps)

/* Функція знаходить кореня системи нелінійних рівнянь методом Ньютона.

Вхідні дані:

X[N] - вектор значень початкового наближення

pSist - вказівник на функцію, яка обчислює по

заданим значенням X[] значення функції f(X) ;

pJakobi - вказівник на функцію, яка обчислює по