Skaitliskās metodes “Interpolācija, izmantojot Ņūtona interpolācijas formulas” (Praktiskais darbs Nr.5 – RA) C++

Rēzeknes Augstskola
Inženieru fakultāte
Datorzinātņu un matemātikas katedra

SKAITLISKĀS METODES

Praktiskais darbs Nr.5
Interpolācija, izmantojot Ņūtona interpolācijas formulas

Fails: **********

Autors
Dienas nodaļas
Inženiera programmētāja specialitātes
2.kursa studente
********
*************

Docētājs
Docents ________________ ***********

Rēzekne 2006

I. Darba uzdevums

Izmantojot Ņūtona interpolācijas formulas, noteikt funkcijas vērtības pie dotajām argumentu vērtībām. Izvadīt galīgo diferenču tabulu, aprēķinātās funkcijas vērtības un attiecīgos atlikuma locekļus kļūdas novērtēšanai. Tabulāros datus ievadīt no faila.
7.variants
x 3,0 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8
y 3,093 4,346 5,766 7,367 9,158 11,149 13,349 15,765 18,401

II. Uzdevuma matemātiskais apraksts

1.Organizēt datu ievadi no faila (t.i., pieprasīt no lietotāja faila nosaukumu, pārbaudīt, vai fails eksistē, nolasīt masīvus x[i] un y[i]).
2.Pieprasīt no lietotāja elementu skaita ievadi.
3.Radīt dinamiskos masīvus: x[i] un y[i] vērtību uzglabāšanai, kā arī divdimensiju matricu ar mainīgu rindas garuma izmēru diferenču tabulas uzglabāšanai un apstrādei.
4.Datu kontrolei izvadīt uz ekrāna no faila iegūtos datus.
4.Aprēķināt vērtību h pēc formulas: h=| x[1]-x[0] |
5.Aizpildīt diferenču tabulas pirmo kolonnu ar y[i] vērtībām.
6.Sākot no otrās kolonnas aizpildīt diferenču tabulu ar izrēķinātajām vērtībām. Pirmās kārtas diferences aprēķina pēc formulas:

Otrās kārtas diferences aprēķina:

Aizpildīt arī pārējo augstāko kārtu diferences, kuras aprēķina pēc formulas:
, kur n – diferences kārta, i – diferences numurs;
6.Izvadīt diferenču tabulu uz ekrāna.
7.Pārbaudīt, vai ievadītā argumenta vērtība atrodas tuvāk intervāla sākumam vai beigām:
7.1.Ja vērtība atrodas tuvāk intervāla sākumam, tad izmanto 1. Ņūtona interpolācijas formulu;
7.2.Ja vērtība atrodas tuvāk intervāla beigām, tad izmanto 2. Ņūtona interpolācijas formulu.
8.Izvēlētajai interpolācijas formulai aprēķina koeficientu q –
8.1. , ja izmanto 1. Ņūtona interpolācijas formulu;
8.2. , ja izmanto 2. Ņūtona interpolācijas formulu;
Kur x – argumenta vērtība, kurai aprēķina funkcijas y vērtību; x0 – intervāla sākuma vērtība; xk – intervāla beigu vērtība; h=xi+1–xi – argumenta x maiņas solis.
9. Aprēķina funkcijas vērtību pēc formulas –
9.1. Ja izmanto 1. Ņūtona interpolācijas formulu:

9.2. Ja izmanto 2. Ņūtona interpolācijas formulu:
10. Nosaka risinājuma kļūdu pēc atlikuma locekļa –
10.1 Ja izmanto I Ņūtona interpolācijas formulu

10.2. Ja izmanto II Ņūtona interpolācijas formulu

11.Aizvērt failu, nodzēst radītos dinamiskos masīvus.
12.Izvadīt uz ekrāna iegūto funkcijas rezultātu un risinājuma kļūdu.
13.Pieprasīt no lietotāja atkārtotu programmas palaišanu, piekrišanas gadījumā atgriezties uz punktu 1., pretējā gadījumā pabeigt programmas darbību.

III. Algoritma blokshēma

IV. Programma
# include <iostream.h>
# include <conio.h>
# include <math.h>
# include <iomanip.h>
# include <fstream.h>
using namespace std;
int main () {
bool choice;
char name[256];
double temp,R,f,q,mid,h,arg;
int p,i,j,k,size,fakt;
ifstream in;
Repeat:
clrscr();
cout<<endl<<“No kaada faila nolasiit datus? : “; cin>>name;
in.open(name);
if (in.fail())
{
cout << “Paarbaudiet faila nosaukumu!” << endl;
exit(1);
}
cout<<endl<<“Cik elementu? : “; cin>>size;
clrscr();
double *x = new double[size];
double *y = new double[size];
double* *diferences = new double* [size];
for(i=0; i<2; i++)
{
for(k=0; k<size; k++)
{
if(i==0)in>>x[k];
else in>>y[k];
}
}
for (i=0; i<size; i++) cout<<x[i]<<“t”; cout<<endl;
for (i=0; i<size; i++) cout<<y[i]<<“t”; cout<<endl; cout<<endl;
h=fabs(x[1]-x[0]);
for (i=0; i<size; i++) diferences[i]=new double[size-i];
for (i=0; i<size; i++)
//aizpilda diferenču tabulas nulto kolonnu ar y vērtībām
{
diferences[i][0]=y[i];
}
for (j=1; j<size; j++)
{
for (i=0; i<=size-j-1; i++)
{
diferences[i][j]=diferences[i+1][j-1]-diferences[i][j-1];
}
}
cout.setf(ios::fixed);
cout.precision(5);
for (i=0; i<size; i++)
{
for (j=0; j<=size-i-1; j++)
cout<<setw(10)<<diferences[i][j];
cout<<endl;
}
mid=fabs((x[0]+x[size-1])/2);
cout<<endl<<“Ievadiet argumentu: “; cin>>arg;
if (mid>arg) //ja meklējamā vērtība tuvāk sākumam
{ //izmantojam pirmo Ņūtona interpolācijas formulu
q=(arg-x[0])/h;
f=diferences[0][0];
temp=q;
fakt=1;
for (i=1; i<size; i++)
{
fakt=fakt*i;
R = temp*diferences[0][i]/fakt;
f = f + R;
temp=temp*(q-i);
}
}
else //ja meklējamā vērtība tuvāk beigām
{ //izmantojam otro Ņūtona interpolācijas formulu
q=(arg-x[size-1])/h;
f = y[size-1];
temp=q;
fakt=1;
for (i=1; i<size; i++)
{
fakt=fakt*i;
R = temp*diferences[size-i-1][i]/fakt;
f = f + R;
temp=temp*(q+i);
}
}
in.close();
delete []x;
delete []y;
do
{
delete[]diferences[size-1];
size–;
}
while(size>0);
delete[]diferences;
cout.precision(7);
cout<<endl<<“Funkcijas veertiiba ir: “<<f;
cout.setf(ios::scientific, ios::floatfield);
cout<<endl<<“Precizitaate ir: “<<R;
cout<<endl<<“Reekjinaat veelreiz? (1-yes / 0-no)”; cin>>choice;
if (choice==TRUE) goto Repeat;
getch();
return 0;
}

V. Kontrolpiemērs

Kontrolpiemēram es izvēlējos šādu sakarības starp x un y tabulu:
X 0 5 10 15 20
Y 6 1 3 9 12

Lai pārbaudītu, vai programma pareizi strādā, rēķinot gan ar pirmo, gan ar otro Ņūtona interpolācijas metodēm, es izvēlējos divas x vērtības, kurām jāaprēķina funkcijas vērtība: 2 un 19.

y y 2y 3y 4y
6 -5 7 -3 -4
1 2 4 -7
3 6 -3
9 3
12

h = 5 – 0 = 5
1) x = 2
„Ar roku” rēķinātais:
q = (2-0)/5 = 2/5 = 0,4
y(x) = 6 + 0,4•(-5) + 7•0,4•(-0,6)/2! + (-3)•0,4•(-0,6) •(-1,6)/3! + (-4) •0,4•(-0,6) •(-1,6) •(-2,6)/4! = 6 – 2 – 0,84 – 0,192 + 0,1664 = 3,1344
Programma uzrādīja šādus rezultātus:

6 -5 7 -3 -4
1 2 4 -7
3 6 -3
9 3
12
Funkcijas veertiiba ir: 3.1344000
Precizitaate ir: 1.6640000e-01

2) x = 19
„Ar roku” rēķinātais:
q = (19-20)/5 = -1/5 = -0,2
y(x) = 12 + 3•(-0,2) + (-3)•(-0,2)•(0,8)/2! + (-7)•(-0,2)•(0,8)•(1,8)/3! + (-4)•(-0,2)•(0,8)•(1,8)•(2,8)/4! = 12 – 0,6 + 0,24 + 0,336 + 0,1344 = 12,1101
Programma uzrādīja šādus rezultātus:

6 -5 7 -3 -4
1 2 4 -7
3 6 -3
9 3
12
Funkcijas veertiiba ir: 12.1104000
Precizitaate ir: 1.3440000e-01

VI. Iegūtais rezultāts

x=2
6.00000 -5.00000 7.00000 -3.00000 -4.00000
1.00000 2.00000 4.00000 -7.00000
3.00000 6.00000 -3.00000
9.00000 3.00000
12.00000

Funkcijas veertiiba ir: 3.1344000
Precizitaate ir: 1.6640000e-01

Reekjinaat veelreiz? (1-yes / 0-no)

x=19
6.00000 -5.00000 7.00000 -3.00000 -4.00000
1.00000 2.00000 4.00000 -7.00000
3.00000 6.00000 -3.00000
9.00000 3.00000
12.00000

Funkcijas veertiiba ir: 12.1104000
Precizitaate ir: 1.3440000e-01

VII. Secinājumi

Kontrolpiemērā „ar roku” rēķinātais pilnīgi sakrita ar programmas iegūtajiem rezultātiem abos gadījumos, kad argumenta x vērtība bija intervāla sākumā un beigās, no kā var secināt, ka programma darbojas korekti.
Neērtības radīja tas, ka uzdevuma noteikumos netika prasīta palīgfunkciju veidošana, kas ļoti atvieglotu programmas rakstīšanas procesu – piemēram, funkcija, kas izskaitļo faktoriālu.
Programma tika optimizēta vairākkārtējai datu ievadei, jo lietotājam ir jāievada vismaz divas vērtības – intervāla sākumā un beigās.
Diemžēl programma ir nepilnīga, jo tā precīzi atrod tikai argumenta vērtības, kuras ir tuvas intervāla robežu vērtībām.

Sandra Lobazova
25.04.2006.