Skaitliskās metodes “Lineāru algebrisku vienādojumu sistēmu atrisināšana ar iterāciju metodēm” (Praktiskais darbs Nr.1 – RA) C++

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

SKAITLISKĀS METODES

Praktiskais darbs Nr.1
Lineāru algebrisku vienādojumu sistēmu atrisināšana ar iterāciju metodēm
Fails: ************

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

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

Rēzekne 2006

I. Darba uzdevums

Atrisināt doto lineāru algebrisku vienādojumu sistēmu ar norādīto precizitāti 10-5, ievērojot konkrētos papildnosacījumus. Izvadīt iegūto rezultātu (sakņu vērtības), sasniegto precizitāti un iterāciju skaitu, kas bija nepieciešams precizitātes sasniegšanai, kā arī katrā iterācijā tās numuru, iegūtos rezultātus un sasniegto precizitāti.
7. 10,56 -1,10 -0,22 -1,40
3,35 19,15 1,52 4,08
0,80 -1,97 12,16 3,15
0,89 -3,06 3,61 -16,96 24,832
53,246
-27,729
47,916 Vienkāršo iterāciju metode Precizitātes noteikšanu katrā iterācijā noformēt kā funkciju

II. Uzdevuma matemātiskais apraksts
1. Pieprasīt no lietotāja ievadīt uzdevuma risināšanai nepieciešamo precizitāti, saglabāt mainīgajā precizitāte.
2. Organizēt ciklu, kas pieprasīs no lietotāja vienādojuma koeficientu matricas ievadi un brīvo locekļu vektora ievadi ar tastatūras palīdzību. Dotos lielumus saglabāt: vienādojumu koeficientu matricu mainīgajā m[4][4], brīvo locekļu vektoru mainīgajā n[4].
3. Organizēt ciklu, kas pārveidos doto vienādojuma koeficientu matricu normālformā un saglabās matricās matrica[4][4] . Šim nolūkam nepieciešams pārbaudīt katru matricas m[4][4] elementu, ja rindas un kolonnas indeksi sakrīt, tad piešķirt atbilstošajam elementam matricā matrica[4][4] vērtību 0. Ja nesakrīt, tad atbilstošajam elementam matricā matrica[4][4] piešķirt vērtību (-m[i][j]/m[i][i] ).
4. Organizēt ciklu, kas pārveidos brīvo locekļu vektoru – izdalīs katru n[i] elementu ar matricas m[i][i] elementu un saglabās mainīgajā vektors[4].
5. Organizēt nulto tuvinājumu saglabāšanu mainīgajā tuvinajums_prev[4], pārrakstot tos no mainīgā vektors[4].
6. Palielināt mainīgo, kas atbildīgs par iterāciju uzskaitīšanu.
7. Piešķirt pašreiz rēķināmajam tuvinājumam mainīgajā vektors[i] esošās vērtības.
8. Uzsākam ciklu. Katram patreizējam tuvinājumam piešķirt vērtību, kas veidota, saskaitot vērtības: tuvinajums_cur[i]+matrica[i][j]*tuvinajums_prev[j].
9. Aprēķināt precizitāti, izsaucot funkciju, kas darbojas šādi (precizitāti saglabāt atsevišķā mainīgajā):
piešķirt mainīgajam, kas glabās precizitātes vērtības, sākuma vērtību nulle;
izveidot ciklu, kas organizēs visu patreizējo tuvinājumu un iepriekšējo tuvinājumu starpības kvadrāta summu;
atgriezt šīs summas kvadrātsaknes vērtību.
10. Izvadīt iterācijas numuru, iegūto precizitāti, iegūtos tuvinājumus.
11. Salīdzināt iegūto precizitāti ar lietotāja ievadīto. Ja iegūtā precizitāte ir mazāka vai vienāda ar to, ko pieprasījis lietotājs, pāriet uz nākošo punktu. Pretējā gadījumā atgriezties uz sesto punktu.
12. Aprēķināt ciparu skaitu aiz komata, ar kuriem izvadīt iegūtās saknes.
13. Izvadīt beidzamās iegūtās saknes, iterāciju skaitu, precizitāti.

III. Algoritma blokshēma


Funkcija precizitate:

Blokshēmā izmantoto mainīgo paskaidrojums:
Preciz – mainīgais, kurā glabājas lietotāja ievadītā precizitāte;
c-mainīgais, kurā tiek saglabāts funkcijas precizitate rezultāts;
i,j –mainīgie, lai strādātu ar ciklu palīdzību strādātu ar masīvu mainīgajiem;
matrica[i][j] –matrica normālveidā;
vektors[i] – matricai a atbilstošs brīvo elementu vektors;
count – mainīgais, kurā uzglabājam iterāciju skaitu;
tuvinajums_prev[i], tuvinajums_cur[i] – iepriekšējais un patreizējais tuvinājumi;
sakne – mainīgais, kurā uzglabājam summu un tās sakni precizitātes aprēķināšanai.

IV. Algoritma blokshēmas apraksts
Bloks 1 – programmas sākums.
Blokā 2 mainīgajam, kas uzglabās funkcijas vērtību, tiek piešķirta sākuma vērtība nulle.
Blokā 3 tiek realizēta vēlamās precizitātes ievade.
Blokos no 4 līdz 7 tiek realizēta vienādojumu koeficientu matricas ievade ar divkāršā cikla palīdzību, kur i,j – attiecīgi rindas un kolonnas indeksi. Ar katru cikla izpildīšanās reizi tiek aizpildīta viena matricas rinda un attiecīgais brīvā locekļu vektora elements.
Blokos no 8 līdz 13 notiek vienādojumu koeficientu matricas un brīvo locekļu vektora apstrāde – pārveidošana normālformā. Tiek organizēts divkāršs cikls, katrā iterācijā tiek pārbaudīti rindas un kolonnas indeksi. Blokā 10 notiek šo indeksu salīdzināšana. Ja tie sakrīt, attiecīgajai matricas vērtībai tiek piešķirta nulles vērtība blokā 11. Ja tie nesakrīt, matricas elementa vērtība tiek izskaitļota, piešķirot pretēju zīmi un izdalot ar atbilstošo elementu, kam dotajā ciklā sakrīt rindas un kolonnas indeksi. Blokā 13 katru reizi, kad tiek palielināts rindas indekss, notiek vektora vērtību izskaitļošana, izdalot to ar elementu, kam dotajā ciklā sakrīt rindas un kolonnas indeksi.
Blokos 14 līdz 15 notiek nulto tuvinājumu vērtību piešķiršana, izmantojot vienkāršu ciklu.
Blokos no 16 līdz 27 ir realizēts algoritms, kurš, izmantojot iepriekš sasniegtus datus aprēķina nākamos tuvinājumus, sasniegtu precizitāti un iterāciju skaitu :
• blokā 16 notiek skaitītāja palielināšana;
• blokos 17 līdz 20 tiek organizēts saliktais cikls, kas realizē patreizējā tuvinājuma vērtības izskaitļošanu;
• blokā 21 tiek izsaukta iepriekš definētā funkcija precizitāte, kuras rezultāts tiek saglabāts mainīgajā c;
• blokā 22 tiek izvadīts iterācijas numurs, nolasot to no skaitītāja;
• blokos 23 līdz 25 tiek realizēts vienkāršs cikls, kas realizē sasniegto tuvinājumu vērtību izvadi un to ievietošanu mainīgajā, kurā tiek uzglabāti iepriekšējie tuvinājumi;
• blokā 26 tiek izvadīta sasniegtā precizitāte;
• blokā 27 notiek iegūtās precizitātes salīdzināšana ar lietotāja ievadīto, ja sasniegtā precizitāte ir mazāka par lietotāja ievadīto, programma pāriet pie bloka 28; pretējā gadījumā programma atgriežas pie bloka 16.
• Blokā 28 mainīgajam džigits tiek piešķirta nulles vērtība;
• Blokos 29-31 notiek vienkārša cikla realizācija, lai noteiktu, ar cik cipariem aiz komata ir jāizvada dotās saknes, atbilstoši lietotāja ievadītajai precizitātei;
• blokos 32-33 notiek iegūto sakņu gala izvade, izmantojot vienkāršu ciklu, sakņu ciparu skaits aiz komata noformatēts atbilstoši lietotāja ievadītajai precizitātei;
• blokā 34 notiek iegūtās precizitātes izvade;
• blokā 35 notiek nepieciešamo iterāciju skaita izvade.
• bloks 36 – funkcijas beigas.
V. Programma
# include <iostream.h>
# include <conio.h>
# include <math.h>
# include <iomanip.h>
double precizitate(double b[4], double a[4])
//funkcija, aprakstīšu šeit
{
double sakne;
sakne=0;
for (int i=0; i<4; i++)
sakne = sakne + pow((a[i] – b[i]), 2);
return sakne = sqrt(sakne);
}
void main () {
double matrica[4][4], vektors[4];
double tuvinajums_cur[4], tuvinajums_prev[4], reizinajums; //tuvinājumi current un previous
int i,j,count=0;
double c,m[4][4],n[4],preciz;
cout<<“ievadiet precizitaati: “;
cin>>preciz;
cout<<endl;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
cout<<“Ievadiet matricas [“<<i+1<<“][“<<j+1<<“]”<<” elementu: “;
cin>>m[i][j];
cout<<endl;
}
cout<<“Ievadiet vektora “<<i+1<<” elementu: “;
cin>>n[i];
cout<<endl;
}
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i==j) { matrica [i][j]=0; }
else { matrica[i][j]=-m[i][j]/m[i][i]; }
}
vektors[i]=n[i]/m[i][i];
}
for (i=0; i<4; i++) tuvinajums_prev[i]=vektors[i];
//nosakām nultos tuvinājumus
//no šīs vietas sāksies cikls
do
{
count++;
for (i=0; i<4; i++)
{
tuvinajums_cur[i]=vektors[i];
for (j=0; j<4; j++)
{
tuvinajums_cur[i]=tuvinajums_cur[i]+matrica[i][j]*tuvinajums_prev[j];
} }
c=precizitate(tuvinajums_prev,tuvinajums_cur);
cout<<endl<<“Iteraacijas numurs: “<<count;
for (i=0; i<4; i++) {
cout<<endl<<“Ieguutaas saknes: “<<tuvinajums_cur[i];
tuvinajums_prev[i]=tuvinajums_cur[i]; }
cout<<endl<<“Precizitaate”<<c;
}
while (c>preciz);
int digits=0;
do
{
digits=digits+1;
preciz=preciz*10;
}
while (preciz<1);
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(digits);
cout<<endl<<“*****************************************************”;
for (i=0; i<4; i++)
{
cout<<endl<<“Ieguutaas saknes: “<<tuvinajums_cur[i];
}
cout<<endl<<“Precizitaate: “<<c;
cout<<endl<<“Ietraaciju skaits: “<<count;
getch();
}

VI. Kontrolpiemērs

Es kontrolpiemēram izvēlējos šādu matricu:

Vienādojumu koeficientu matrica A Brīvo locekļu vektors C
10 2 2 2 1
2 10 2 2 2
2 2 10 2 -3
2 2 2 10 -4
Un precizitāti: 0.1.
Programma nonāca pie šāda rezultāta:
Iteraacijas numurs: 1
Ieguutaas saknes: 0.2
Ieguutaas saknes: 0.32
Ieguutaas saknes: -0.28
Ieguutaas saknes: -0.4
Precizitaate0.15748
Iteraacijas numurs: 2
Ieguutaas saknes: 0.172
Ieguutaas saknes: 0.296
Ieguutaas saknes: -0.324
Ieguutaas saknes: -0.448
Precizitaate0.0748331
*****************************************************
Ieguutaas saknes: 0.2
Ieguutaas saknes: 0.3
Ieguutaas saknes: -0.3
Ieguutaas saknes: -0.4
Precizitaate: 0.1
Ietraaciju skaits: 2
Sasniegtā precizitāte=0,1
Nepieciešamo iterāciju skaits: 2.
Rēķinot „ar roku”, risināšanas etapi:
1) pārveidojam normālformā:
0 0,2 0,2 0,2 0,1
0,2 0 0,2 0,2 0,2
0,2 0,2 0 0,2 -0,3
0,2 0,2 0,2 0 -0,4
2) rēķinām pirmo tuvinājumu un precizitāti:

3)

VII. Iegūtais rezultāts

Iteraacijas numurs: 1
Ieguutaas saknes: 2.21908
Ieguutaas saknes: 3.12993
Ieguutaas saknes: -1.25273
Ieguutaas saknes: -3.68888
Precizitaate1.39339
Iteraacijas numurs: 2
Ieguutaas saknes: 2.1624
Ieguutaas saknes: 3.25678
Ieguutaas saknes: -0.963677
Ieguutaas saknes: -3.54015
Precizitaate0.35352
Iteraacijas numurs: 3
Ieguutaas saknes: 2.20135
Ieguutaas saknes: 3.2126
Ieguutaas saknes: -0.977925
Ieguutaas saknes: -3.50449
Precizitaate0.0703158
Iteraacijas numurs: 4
Ieguutaas saknes: 2.20118
Ieguutaas saknes: 3.19896
Ieguutaas saknes: -0.996884
Ieguutaas saknes: -3.4975
Precizitaate0.0243824
Iteraacijas numurs: 5
Ieguutaas saknes: 2.20029
Ieguutaas saknes: 3.199
Ieguutaas saknes: -1.00089
Ieguutaas saknes: -3.49909
Precizitaate0.00440097
Iteraacijas numurs: 6
Ieguutaas saknes: 2.2
Ieguutaas saknes: 3.19982
Ieguutaas saknes: -1.00042
Ieguutaas saknes: -3.5
Precizitaate0.00134438
Iteraacijas numurs: 7
Ieguutaas saknes: 2.19997
Ieguutaas saknes: 3.20003
Ieguutaas saknes: -1.00003
Ieguutaas saknes: -3.50006
Precizitaate0.000444926
Iteraacijas numurs: 8
Ieguutaas saknes: 2.2
Ieguutaas saknes: 3.20002
Ieguutaas saknes: -0.999978
Ieguutaas saknes: -3.50001
Precizitaate7.18876e-05
Iteraacijas numurs: 9
Ieguutaas saknes: 2.2
Ieguutaas saknes: 3.2
Ieguutaas saknes: -0.999993
Ieguutaas saknes: -3.5
Precizitaate2.74982e-05
Iteraacijas numurs: 10
Ieguutaas saknes: 2.2
Ieguutaas saknes: 3.2
Ieguutaas saknes: -1
Ieguutaas saknes: -3.5
Precizitaate7.50036e-06
*****************************************************
Ieguutaas saknes: 2.20000
Ieguutaas saknes: 3.20000
Ieguutaas saknes: -1.00000
Ieguutaas saknes: -3.50000
Precizitaate: 0.00001
Ietraaciju skaits: 10

VIII. Secinājumi

Pildot šo darbu, es nonācu pie viena galvenā secinājuma – dažkārt sarežģītas operācijas var veikt ar vienkāršiem operatoriem, nenoslogojot lieki nedz sevi, nedz datora resursus. Turklāt vienkāršo iterāciju metode jau pēc nosaukuma vien ir vienkāršāka, nekā Zeideļa, tāpēc programmu varēju sastādīt no būtībā elementāriem blokiem.
Lai gan samērā izpildē vienkārša, šī programma prasīja lielu vērību mazās detaļās, jo nesvarīgas kļūdas sintaksē noveda pie sistēmas „uzkāršanās”.
Izvēloties kontrolpiemēru, es izvēlēju vienkāršu vienādojumu sistēmu (ar veseliem skaitļiem) un nelielu precizitāti.
Tā kā kontrolpiemēra rezultāts sakrita ar roku risināto, varu secināt, ka programma darbojas korekti.

Sandra Lobazova
06.03.2006.