Rēzeknes Augstskola
Inženieru fakultāte
Datorzinātņu un matemātikas katedra
Praktiskais darbs Nr.2
Algebrisku nelineāru un transcendentu vienādojumu atrisināšanas tuvinātās metodes
Fails: **********_2.cpp
Autors
Dienas nodaļas
Inženiera programmētāja specialitātes
2.kursa studente
************
**************
Docētājs
Docents ________________ ***********
I. Darba uzdevums
Atrisināt doto vienādojumu, lietojot norādīto metodi. Paredzēt argumenta x un funkcijas f(x) izvadu katrā iterācijā. Par iterācijas beigu nosacījumu pieņemt precizitāti 10-5. Izvadīt vienādojuma sakni, sasniegto precizitāti un iterāciju skaitu, kas bija nepieciešams saknes atrašanai. Aprēķinus veikt divas reizes: doto intervālu dalot 10 un 100 daļās.
Nr.VienādojumsIntervālsMetodePapildnosacījumi
7.x3 + x + 1 = 00;1DihotomijasSaknes atdalīšanas etapu noformēt funkcijas veidā
1.Lietotājs ievada intervāla sākuma un beigu punktus, cik daļās intervālu dalīt, kā arī precizitāti.
2.Izveidot funkciju, kas meklē nepieciešamo intervālu pēc šāda principa:
* paņem intervāla sākumpunktu; par intervāla galapunktu pieņem vērtību (sākumpunkts+solis);
* aprēķina uzdoto funkciju abiem galapunktiem;
* ja galapunktos funkcijas vērtības atšķiras, vajadzīgais intervāls ir atrasts;
* ja, izejot visu lietotāja uzdoto intervālu, nav atrasts tāds intervāls, kas atbilst iepriekšējam punktam, paredzēt atbilstoša mainīgā saglabāšanu, kas „signalizēs” par piemērota intervāla neesamību.
3.Ja neeksistē intervāls, kurā atrodas sakne, paredzēt atbilstoša ziņojuma izvadi un programmas darbības izbeigšanu.
4.Ja piemērots intervāls eksistē, uzsākt ciklu saknes meklēšanai, kas izbeigsies, ja iegūtās saknes un iepriekš iegūtās saknes starpība būs mazāka par lietotāja uzdoto precizitāti:
* aprēķina viduspunktu starp intervāla galapunktiem;
* aprēķina funkcijas vērtību vienā no galapunktiem;
* atrod funkcijas vērtību viduspunktā;
* ja funkcijas vērtība viduspunktā un aplūkotajā galapunktā sakrīt, tad aplūkoto galapunktu pārnest uz viduspunktu, pretējā gadījumā pārnest uz viduspunktu otru galapunktu.
* paredzēt viduspunkta, iterācijas numura, precizitātes, funkcijas vērtības izvadi.
5. Paredzēt gala rezultātu (saknes, iterāciju skaita, precizitātes) izvadi noformatētā veidā.
Funkcija intervals :
IV. Programma
# include <iostream.h>
# include <math.h>
# include <conio.h>
# include <stdlib.h>
# include <iomanip.h>
double funkcija (double x) //f-ja,kas izskaitljos x veertiibu
{
return pow(x,3)+x+1;
}
double intervals (double a, double b, double solis)
//f-ja, kas izskaitljos intervaalu
{
double curr_loc, prev_loc,location=0;
bool flag; //nepiecieshams, lai vereetu noteikt, vei intervaals eksistee
for ( prev_loc=a; prev_loc<b; prev_loc=prev_loc+solis )
{
curr_loc=prev_loc+solis;
if ( funkcija(prev_loc)*funkcija(curr_loc) < 0 )
{
location=prev_loc; //atradaam intervaala saakumu
flag=true; //noraadaam, ka intervaals eksistee
break; //izejam no cikla
}
}
if (flag==TRUE) return location;
else return 0;
//ja intervaals neeksistee, f-ja atgrieziis nulli
}
void main () {
double x,a,b,solis,c,d,e,preciz,f1,f2,prev=0; int i,n,count=0,digits=0;
cout<<"Ievadiet intervaala saakuma veertiibu: "; cin>>a; cout<<endl;
cout<<"Ievadiet intervaala beigu veertiibu: "; cin>>b; cout<<endl;
cout<<"Ievadiet, uz cik intervaaliem jaadala: "; cin>>n; cout<<endl;
cout<<"Ievadiet nepiecieshamo precizitaati: "; cin>>preciz; cout<<endl;
solis = (fabs(a) + fabs(b))/ n; //apreekjina intervaala sadaliijumu pa soljiem
if (intervals(a,b,solis)==0) //ja intervaals neeksistee, tad funkcijas veertiiba ir nulle
cout<<"Dotajaa intervaalaa vienaadojumam saknju nav!";
else //ja sakne dotajaa intervaalaa eksistee, tad:
{
c=intervals(a,b,solis); //apreekjina mekleejamaa intervaala saakuma veertibu
d=c+solis; //un beigu veertiibu
do //uzsaak ciklu liidz nepiec.precizitaates sasniegshanai
{
count++; //skaitiitaajs
x=(c+d)/2; //x atrodas intervaala viduu
f1=funkcija(x); //atrodam f(x) dotajaa punktaa x
f2=funkcija(c);
cout<<endl<<"Iteraacijas Nr.: "<<count<<" un x v-ba: "<<x<<" f(x)="<<f1;
if ((f1*f1)<0) d=x;
/*ja viduspunkta funkcijas un intervaala saakuma funkcijas ziimes
nesakriit, tad tiek izdariita galapunkta paarnese uz otro intervaala robezhu,
preteejaa gadiijumaa notiek paarnese uz punktu, ar ko saliidzina*/
else c=x;
e=fabs(x-prev);
prev=x;
cout<<" un precizitaate: "<<e;
}
while (preciz<e);
x=(x+prev)/2; //beigu x veertiiba
do
{
digits=digits+1;
preciz=preciz*10;
}
while (preciz<1);
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(digits);
cout<<endl<<"*****************************************";
cout<<endl<<"Kopaa bija nepiecieshamas "<<count<<" iteraacijas.";
cout<<endl<<"Beigu x v-ba: "<<x;
cout<<endl<<"Un precizitaate: "<<e;
}
getch();
}
Tā kā vienādojumam pie visiem pozitīviem x funkcijas vērtība arī ir pozitīva, intervālā, kurā visi x ir pozitīvi, funkcijai nebūs saknes. Tāpēc izvēlējos kontrolpiemēram tādu apgabalu, kurā funkcijai iespējamas saknes: [-2; 0]. Par precizitāti pieņēmu 10-1, intervālu dalīju 4 daļās. Rēķinot ar roku, nonācu pie šāda rezultāta:
Solis = ( |-2| + |0| )/4 = 0,5
1)Meklēju intervālu:
f(-2) = (-2)3+(-2)+1= - 9
f(-1,5) = (-1,5)3+(-1,5)+1 = - 3,875
f(-1) = (-1)3+(-1)+1= - 1
f(-0,5) = (-0,5)3+(-0,5)+1 = 0,375 (zīmes atšķiras, intervāls atrasts)
2)Meklēju sakni intervālā [-1;-0,5]
•((-1)+(-0,5))/2 = -0,75
f(-0,75) = -0,171875 pārnes a uz x;
•((-0,75)+(-0,5))/2=-0,625
f(-0,625) = 0,1308594 pārnes b uz x;
precizitāte = 0,125 >0.1
•((-0,625)+(-0,75))/2 = -0,6875
f(-0,6875) = -0,0124511 pārnes a uz x;
precizitāte = 0,0625<0.1
sakne = ((-0,6875)+(-0,625))/2 = 0,65625
3)sakne = 0,7; iterāciju skaits=3; precizitāte = 0,1
Rēķinot ar programmu, nonācu pie šādiem rezultātiem:
Iteraacijas Nr.: 1 un x v-ba: -0.75 f(x)=-0.171875 un precizitaate: 0.75
Iteraacijas Nr.: 2 un x v-ba: -0.625 f(x)=0.130859 un precizitaate: 0.125
Iteraacijas Nr.: 3 un x v-ba: -0.6875 f(x)=-0.0124512 un precizitaate: 0.0625
*****************************************
Kopaa bija nepiecieshamas 3 iteraacijas.
Beigu x v-ba: -0.7
Un precizitaate: 0.1
1.Dalot intervālu uz 10 daļām:
Ievadiet intervaala saakuma veertiibu: 0
Ievadiet intervaala beigu veertiibu: 1
Ievadiet, uz cik intervaaliem jaadala: 10
Ievadiet nepiecieshamo precizitaati: 0.00001
Dotajaa intervaalaa vienaadojumam saknju nav!
2.Dalot intervālu uz 100 daļām:
Ievadiet intervaala saakuma veertiibu: 0
Ievadiet intervaala beigu veertiibu: 1
Ievadiet, uz cik intervaaliem jaadala: 100
Ievadiet nepiecieshamo precizitaati: 0.00001
Dotajaa intervaalaa vienaadojumam saknju nav!
Ņemot intervālu, kurā dotajai funkcijai eksistē atrisinājums, un izdarot eksperimentu vairākas reizes, es konstatēju, ka: pie vienādas precizitātes un norādītā intervāla – dalot vairākās daļās, nepieciešams mazāk iterāciju, lai sasniegtu vajadzīgo precizitāti.
Tā kā kontrolpiemērā atrastā sakne sakrita ar programmas atrasto, varu secināt, ka programma darbojas korekti.
Arī pie lielas precizitātes programma darbojās ātri, tāpēc varu secināt, ka Ar dihotomijas metodes palīdzību nelineārus un transcendentus vienādojumus var atrisināt diezgan ātri, turklāt šo metodi var diezgan viegli realizēt C++ valodā.
Sandra Lobazova
07.03.2006.