Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2025 mgr Jerzy Wałaszek
|
W naszym serwisie jest nowszy artykuł o obliczaniu pierwiastków funkcji: "Metody numeryczne".
SPIS TREŚCI |
Podrozdziały |
Mamy dany układ n równań liniowych z n niewiadomymi. Zapiszmy go następująco:
Następnie utwórzmy macierz A współczynników ai,j tego układu równań oraz wektor kolumnowy B wyrazów bi:
Macierz A jest macierzą kwadratową o wymiarze n × n. Niech W = det A. Jeśli wyznacznik W jest różny od 0 (pamiętajmy o błędach zaokrągleń - sprawdzamy, czy wyznacznik W leży w otoczeniu ε wartości 0), to układ równań posiada rozwiązania. W przeciwnym razie układ równań jest sprzeczny lub liniowo zależny i nie posiada jednoznacznego rozwiązania.
Aby znaleźć wartości kolejnych niewiadomych, postępujemy następująco:
W macierzy A współczynników dla każdej niewiadomej xi , i = 1, 2, ... , n, zastępujemy i-tą kolumnę wektorem kolumnowym B. Następnie wyliczamy wyznacznik Wi tak zmodyfikowanej macierzy. Wartość kolejnych niewiadomych xi , i = 1, 2, ... , n, otrzymamy za pomocą poniższego wzoru:
Metoda ta nosi nazwę wzorów Cramera (ang. Cramer's Rule).
Przykład:
Rozwiążemy przy pomocy podanych powyżej wzorów Cramera układ 3 równań liniowych z trzema niewiadomymi x1, x2 i x3:
Najpierw tworzymy macierz A współczynników oraz wektor kolumnowy B:
Wykorzystując regułę Sarrusa obliczamy wyznacznik główny W:
Teraz dla niewiadomej x1 w macierzy A zastępujemy kolumnę nr 1 wektorem B i obliczamy jej wyznacznik W1:
Podobnie postępujemy dla pozostałych niewiadomych:
Podsumujmy otrzymane wyniki:
Zgodnie ze wzorami Cramera mamy:
Technicznie macierz A
współczynników oraz wektor kolumnowy B będziemy
przechowywać w jednej tablicy o n wierszach i
AB = | 1 | 2 | 3 | ... | n-1 | n | n+1 | ||
a1,1 | a1,2 | a1,3 | ... | a1,n-1 | a1,n | b1 | |||
a2,1 | a2,2 | a2,3 | ... | a2,n-1 | a2,n | b2 | |||
a3,1 | a3,2 | a3,3 | ... | a3,n-1 | a3,n | b3 | |||
... | ... | ... | ... | ... | ... | ... | |||
an-1,1 | an-1,2 | an-1,3 | ... | an-1,n-1 | an-1,n | bn-1 | |||
an,1 | an,2 | an,3 | ... | an,n-1 | an,n | bn |
n | – | ilość niewiadomych oraz układów równań. n ∈ N, n < 9 |
AB[ ] | – | tablica n(n+1)
elementowa zawierająca współczynniki ai,j
oraz wyrazy wolne bi,
ai,j,bi ∈
R; i,j ∈ N,
|
X[ ] | – | tablica n elementowa zawierająca wartości kolejnych niewiadomych xi. xi ∈ R , i ∈ N , i = 1,2,...,n, lub informacja, iż dany układ równań nie posiada jednoznacznego rozwiązania. |
det(stopień,wiersz,wektorkolumn[], macierz[]) | – funkcja wyliczająca odpowiedni wyznacznik |
W | – | wyznacznikiem główny układu równań. |
WK[ ] | – | wektor kolumn zawierający numery kolumn tablicy AB[ ]. Wykorzystywany jest do podmiany kolumny z wyrazami wolnymi bi w miejsce kolumny współczynników dla odpowiedniej zmiennej. |
i | – | zmienna sterująca pętli, i ∈ N |
ε | – | określa dokładność porównania z zerem. ε = 0.0000000001 |
K01: | Dla i =
1, 2, ..., n: wykonuj WK[i] ← i |
|
K02: | W ← det(n, 1, WK[ ]) | |
K03: | Jeśli
| W
| < ε , to pisz "Brak rozwiązania" i zakończ |
|
K04: | Dla i =
1, 2, ..., n: wykonuj kroki K05...K07 |
|
K05: | WK[i] ← n + 1 | |
K06: | X[i] ← det(n,1,WK[ ], AB[ ]) | |
K07: | WK[i] ← i | |
K08: | Zakończ |
Algorytm rozpoczynamy od ustawienia wektora kolumn
Następnie obliczamy wyznacznik macierzy współczynników aij. Wartość wyznacznika zapamiętujemy w zmiennej W.
Jeśli wyznacznik główny W wpada w otoczenie zera o promieniu ε, to układ równań nie posiada jednoznacznego rozwiązania. Wypisujemy odpowiednią informację i kończymy algorytm.
W przeciwnym razie rozwiązanie istnieje. W
Po zakończeniu pętli nr 2 w tablicy
Prezentowane poniżej przykładowe programy odczytują dane z pliku in.txt i zapisują wyniki do pliku out.txt. Przyjęliśmy to rozwiązanie z uwagi na dużą liczbę danych, które muszą być dostarczone do programu - klawiatura nie byłaby zbyt wygodna. Pliki znajdują się w bieżącym katalogu. Plik in.txt powinien posiadać następującą strukturę:
W pierwszym wierszu liczba od 1 do 8 (ważne, gdyż z uwagi na czasochłonność obliczeń ograniczyłem maksymalny rozmiar macierzy do przechowania maksymalnie 8 równań) określająca ilość równań, czyli n.
W następnych n wierszach powinny być umieszczone współczynniki. Jeden wiersz określa współczynniki jednego równania. Kolejne współczynniki powinny być od siebie oddzielone przynajmniej jedną spacją. Pierwsze n współczynników odnosi się do współczynników przy kolejnych niewiadomych. Ostatni (n+1)-szy współczynnik określa wyraz wolny bi. Programy uruchomiono z plikiem in.txt o następującej zawartości:
5 2 -2 2 -7 6 -4 7 -3 -2 7 2 11 2 2 -1 1 4 9 9 8 -2 2 -2 21 4 8 -3 3 -1 16 |
Plik określa układ 5 równań liniowych:
2x1 | - | 2x2 | + | 2x3 | - | 7x4 | + | 6x5 | = | -4 |
7x1 | - | 3x2 | - | 2x3 | + | 7x4 | + | 2x5 | = | 11 |
2x1 | + | 2x2 | - | x3 | + | x4 | + | 4x5 | = | 9 |
9x1 | + | 8x2 | - | 2x3 | + | 2x4 | - | 2x5 | = | 21 |
4x1 | + | 8x2 | - | 3x3 | + | 3x4 | - | x5 | = | 16 |
C++// Program rozwiązuje układ równań liniowych o n niewiadomych // za pomocą metody wyznacznikowej Cramera. n <= 8 //----------------------------------------------------------- // (C)2006 mgr J.Wałaszek I LO w Tarnowie #include <iostream> #include <iomanip> #include <fstream> #include <cmath> #include <cstdlib> using namespace std; // Rekurencyjna funkcja obliczania wyznacznika //-------------------------------------------- long double det(int stopien, int wiersz, int wk[], double A[][9]) { int i,j,k,m; int kolumny[8]; // wektor kolumn dla podmacierzy long double suma; if(stopien == 1) return A[wiersz][wk[0]]; else { suma = 0; m = 1; for(i = 0; i < stopien; i++) { k = 0; for(j = 0; j < stopien - 1; j++) { if(k == i) k++; kolumny[j] = wk[k++]; } suma += m * A[wiersz][wk[i]] * det(stopien - 1, wiersz + 1, kolumny, A); m = -m; } return suma; } } //----------------------------------------------------- // Program główny //----------------------------------------------------- int main() { const double EPS = 0.0000000001; // dokładność porównania z zerem ifstream fin; ofstream fout; int i,j,n,WK[8]; double AB[8][9],X[8]; long double W; cout << setprecision(2) // 2 cyfry po przecinku << fixed; // format stałoprzecinkowy cout << "Demonstracja rozwiazywania ukladu rownan metoda Cramera\n" "-------------------------------------------------------\n" "(C)2006 mgr Jerzy Walaszek I LO w Tarnowie\n\n"; // Dane dla programu odczytujemy z pliku tekstowego o nazwie in.txt, // który musi się znajdować w tym samym katalogu co program // Pierwszy wiersz pliku powinien zawierać liczbę n // Następne n kolejnych wierszy powinno zawierać współczynniki ai dla // tego wiersza, a na końcu współczynnik bi. Kolejne współczynniki // oddzielone są od siebie przynajmniej jedną spacją. fin.open("in.txt"); fin >> n; if(n <= 8) { for(i = 0; i < n; i++) for(j = 0; j <= n; j++) fin >> AB[i][j]; fin.close(); // Wyświetlamy wczytany układ równań w oknie konsoli for(i = 0; i < n; i++) for(j = 0; j <= n; j++) { if(!j) cout << setw(5) << AB[i][j]; else if(j == n) cout << "= " << setw(5) << AB[i][j] << endl; else { if(AB[i][j] > 0) cout << "+" << setw(5) << AB[i][j]; else cout << "-" << setw(5) << fabs(AB[i][j]); } if(j < n) cout << "*x" << j + 1 << " "; } cout << "\n-------------------------------------------------------\n" "Wyniki:\n\n"; // Otwieramy plik wyników out.txt fout.open("out.txt"); // Obliczamy wyznacznik główny for(i = 0; i < n; i++) WK[i] = i; W = det(n,0,WK,AB); if(fabs(W) < EPS) cout << "Brak rozwiazania\n"; else { // Obliczamy kolejne wyznaczniki Wi for(i = 0; i < n; i++) { WK[i] = n; // podmieniamy kolumnę współczynnikami bi X[i] = det(n,0,WK,AB) / W; WK[i] = i; // przywracamy kolumnę współczynników ai } // Wypisujemy wyniki do okna konsoli oraz do pliku out.txt for(i = 0; i < n; i++) { cout << "x" << i + 1 << " = " << setw(10) << X[i] << endl; fout << X[i] << endl; } fout.close(); } } else { fin.close(); cout << "Zbyt wiele rownan!\n"; } cout << "\n-------------------------------------------------------\n\n"; system("pause"); return 0; } |
Pascal// Program rozwiązuje układ równań liniowych o n niewiadomych // za pomocą metody wyznacznikowej Cramera. n <= 8 //----------------------------------------------------------- // (C)2006 mgr J.Wałaszek I LO w Tarnowie program mzfl4; {$APPTYPE CONSOLE} const EPS = 0.0000000001; // dokładność porównania z zerem type kwektor = array[1..8] of integer; macierz = array[1..8,1..9] of double; // Rekurencyjna funkcja obliczania wyznacznika //-------------------------------------------- function det(stopien, wiersz : integer; var wk : kwektor; var A : macierz) : extended; var i,j,k,m : integer; kolumny : kwektor; // wektor kolumn dla podmacierzy begin if stopien = 1 then Result := A[wiersz,wk[1]] else begin Result := 0; m := 1; for i := 1 to stopien do begin k := 1; for j := 1 to stopien - 1 do begin if k = i then inc(k); kolumny[j] := wk[k]; inc(k); end; Result := Result+m*A[wiersz,wk[i]]*det(stopien-1,wiersz+1,kolumny,A); m := -m; end; end; end; //----------------------------------------------------- // Program główny //----------------------------------------------------- var f : Text; i,j,n : integer; AB : macierz; W : extended; X : array[1..8] of double; WK : kwektor; begin writeln('Demonstracja rozwiazywania ukladu rownan metoda Cramera'); writeln('-------------------------------------------------------'); writeln('(C)2006 mgr Jerzy Walaszek I LO w Tarnowie'); writeln; // Dane dla programu odczytujemy z pliku tekstowego o nazwie in.txt, // który musi się znajdować w tym samym katalogu co program // Pierwszy wiersz pliku powinien zawierać liczbę n // Następne n kolejnych wierszy powinno zawierać współczynniki ai dla // tego wiersza, a na końcu współczynnik bi. Kolejne współczynniki // oddzielone są od siebie przynajmniej jedną spacją. assignfile(f,'in.txt'); reset(f); readln(f,n); if n <= 8 then begin for i := 1 to n do for j := 1 to n + 1 do read(f,AB[i,j]); closefile(f); // Wyświetlamy wczytany układ równań w oknie konsoli for i := 1 to n do for j := 1 to n + 1 do begin if j = 1 then write(AB[i,j]:5:2) else if j = n + 1 then writeln('= ',AB[i,j]:5:2) else begin if AB[i,j] > 0 then write('+',AB[i,j]:5:2) else write('-',abs(AB[i,j]):5:2); end; if j <= n then write('*x',j,' '); end; writeln; writeln('-------------------------------------------------------'); writeln('Wyniki:'); writeln; // Otwieramy plik wyników out.txt assignfile(f,'out.txt'); rewrite(f); // Obliczamy wyznacznik główny for i := 1 to n do WK[i] := i; W := det(n,1,WK,AB); if abs(W) < EPS then writeln('Brak rozwiazania') else begin // Obliczamy kolejne wyznaczniki Wi for i := 1 to n do begin WK[i] := n + 1; // podmieniamy kolumnę współczynnikami bi X[i] := det(n,1,WK,AB) / W; WK[i] := i // przywracamy kolumnę współczynników ai end; // Wypisujemy wyniki do okna konsoli oraz do pliku out.txt for i := 1 to n do begin writeln('x',i,' = ',X[i]:10:5); writeln(f,X[i]); end; end; end else writeln('Za wiele rownan!'); closefile(f); writeln; writeln('-------------------------------------------------------'); writeln('Koniec. Nacisnij klawisz Enter...'); readln; end. |
Basic' Program rozwiązuje układ równań liniowych o n niewiadomych ' za pomocą metody wyznacznikowej Cramera. n <= 8 '----------------------------------------------------------- ' (C)2006 mgr J.Wałaszek I LO w Tarnowie Declare Function det(stopien As Integer, wiersz As Integer, wk() As Integer, A() As Double) As Double const EPS As Double = 0.0000000001 ' dokładność porównania z zerem '----------------------------------------------------- ' Program główny '----------------------------------------------------- Dim As Integer i,j,n,WK(7) Dim As double AB(7,8),X(7),W Print "Demonstracja rozwiazywania ukladu rownan metoda Cramera" Print "-------------------------------------------------------" Print "(C)2006 mgr Jerzy Walaszek I LO w Tarnowie" Print ' Dane dla programu odczytujemy z pliku tekstowego o nazwie in.txt, ' który musi się znajdować w tym samym katalogu co program ' Pierwszy wiersz pliku powinien zawierać liczbę n ' Następne n kolejnych wierszy powinno zawierać współczynniki ai dla ' tego wiersza, a na końcu współczynnik bi. Kolejne współczynniki ' oddzielone są od siebie przynajmniej jedną spacją. Open "in.txt" For Input As #1 Input #1,n if n <= 8 Then For i = 0 to n - 1 for j = 0 to n: Input #1, AB(i,j): Next Next ' Wyświetlamy wczytany układ równań w oknie konsoli for i = 0 to n - 1 for j = 0 to n if j = 0 Then print Using "##.##";AB(i,j); ElseIf j = n Then Print Using " = ##.##";AB(i,j) Else Print Using " +##.##";AB(i,j); End If if j < n then Print Using "*X#";j+1; Next Next Print Print "-------------------------------------------------------" Print "Wyniki:" Print ' Otwieramy plik wyników out.txt Open "out.txt" For Output As #2 ' Obliczamy wyznacznik główny for i = 0 to n-1: WK(i) = i: Next W = det(n,0,WK(),AB()) if abs(W) < EPS then Print #2,"Brak rozwiazania" Print "Brak rozwiazania" Else ' Obliczamy kolejne wyznaczniki Wi for i = 0 to n - 1 WK(i) = n ' podmieniamy kolumnę współczynnikami bi X(i) = det(n,0,WK(),AB()) / W WK(i) = i ' przywracamy kolumnę współczynników ai Next ' Wypisujemy wyniki do okna konsoli oraz do pliku out.txt for i = 0 to n - 1 print #2,Using "x# = ####.#####";i;X(i) print Using "x# = ####.#####";i;X(i) Next Close #2 End If Else Print "Za wiele rownan!" End If Close #1 Print Print "-------------------------------------------------------" Print "Koniec. Nacisnij klawisz Enter..." Sleep End ' Rekurencyjna funkcja obliczania wyznacznika '-------------------------------------------- Function det(stopien As Integer, wiersz As Integer, wk() As Integer, A() As Double) As Double Dim As Integer i, j, k, m Dim kolumny(7) As Integer ' wektor kolumn dla podmacierzy Dim suma As Double If stopien = 1 Then return A(wiersz, wk(0)) Else suma = 0 : m = 1 For i = 0 To stopien - 1 k = 0 For j = 0 To stopien - 2 If k = i Then k += 1 kolumny(j) = wk(k) k += 1 Next suma += m * A(wiersz, wk(i)) * det(stopien - 1, wiersz + 1, kolumny(), A()) m = -m Next Return suma End If End Function |
Wynik: |
Demonstracja rozwiązywania
układu równań metodą Cramera ------------------------------------------------------- (C)2006 mgr Jerzy Wałaszek I LO w Tarnowie 2,00*x1 - 2,00*x2 + 2,00*x3 - 7,00*x4 + 6,00*x5 = -4,00 7,00*x1 - 3,00*x2 - 2,00*x3 + 7,00*x4 + 2,00*x5 = 11,00 2,00*x1 + 2,00*x2 - 1,00*x3 + 1,00*x4 + 4,00*x5 = 9,00 9,00*x1 + 8,00*x2 - 2,00*x3 + 2,00*x4 - 2,00*x5 = 21,00 4,00*x1 + 8,00*x2 - 3,00*x3 + 3,00*x4 - 1,00*x5 = 16,00 ------------------------------------------------------- Wyniki: x0 = 1,00000 x1 = 2,00000 x2 = 3,00000 x3 = 2,00000 x4 = 1,00000 ------------------------------------------------------- Koniec. Naciśnij klawisz Enter... |
Program w JavaScript pobiera dane z okna tekstowego. Spowodowane jest to tym, iż w JavaScript dostęp do plików komputera użytkownika jest ograniczony - przecież nie chciałbyś, aby jakaś strona WWW buszowała po dysku twardym twojego komputera - byłby to raj dla hackerów.
Dane dla układu równań możesz wkleić poprzez schowek do okna tekstowego formularza.
JavaScript<html> <head> </head> <body> <div align="center"> <form style="BORDER-RIGHT: #ff9933 1px outset; PADDING-RIGHT: 4px; BORDER-TOP: #ff9933 1px outset; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: #ff9933 1px outset; PADDING-TOP: 1px; BORDER-BOTTOM: #ff9933 1px outset; BACKGROUND-COLOR: #ffcc66" name="frmbincode"> <h3 style="TEXT-ALIGN: center"> Demonstracja rozwiązywania układu równań<br> metodą Cramera </h3> <p style="TEXT-ALIGN: center"> (C)2006 mgr Jerzy Wałaszek I LO w Tarnowie </p> <hr> <p style="TEXT-ALIGN: center"> Tutaj wprowadź wiersze ze współczynnikami układu równań: </p> <p style="TEXT-ALIGN: center"> <textarea rows="9" name="input" cols="70">5 2 -2 2 -7 6 -4 7 -3 -2 7 2 11 2 2 -1 1 4 9 9 8 -2 2 -2 21 4 8 -3 3 -1 16</textarea> </p> <p style="TEXT-ALIGN: center"> <input type="button" value="Rozwiąż układ równań" name="B1" onclick="main()"> </p> <div id="out" align=center>...</div> </form> <script language=javascript> // Program rozwiązuje układ równań liniowych o n niewiadomych // za pomocą metody wyznacznikowej Cramera. n <= 8 //----------------------------------------------------------- // (C)2006 mgr J.Wałaszek I LO w Tarnowie // Rekurencyjna funkcja obliczania wyznacznika //-------------------------------------------- function det(stopien, wiersz, wk, A) { var i,j,k,m; var kolumny = new Array(8); // wektor kolumn dla podmacierzy var suma; if(stopien == 1) return A[wiersz][wk[0]]; else { suma = 0; m = 1; for(i = 0; i < stopien; i++) { k = 0; for(j = 0; j < stopien - 1; j++) { if(k == i) k++; kolumny[j] = wk[k++]; } suma += m * A[wiersz][wk[i]] * det(stopien - 1, wiersz + 1, kolumny, A); m = -m; } return suma; } } //----------------------------------------------------- // Program główny //----------------------------------------------------- function main() { var EPS = 0.0000000001; // dokładność porównania z zerem var i,j,k,n,W,t,s,z; var WK = new Array(8); var AB = new Array(8); var X = new Array(8); // Dane dla programu odczytujemy z pola tekstowego. // Pierwszy wiersz pola powinien zawierać liczbę n // Następne n kolejnych wierszy powinno zawierać współczynniki ai dla // tego wiersza, a na końcu współczynnik bi. Kolejne współczynniki // oddzielone są od siebie przynajmniej jedną spacją. t = "<font color=red><b>Złe dane</b></font>"; s = document.frmbincode.input.value; if(s.length > 0) { // Odczytujemy współczynniki z pola tekstowego formularza while((j = s.indexOf('\n')) != -1) s = s.substring(0,j) + " " + s.substring(j + 1,s.length); while((j = s.indexOf('\r')) != -1) s = s.substring(0,j) + " " + s.substring(j + 1,s.length); while((j = s.indexOf('\t')) != -1) s = s.substring(0,j) + " " + s.substring(j + 1,s.length); while(s.length > 0 && (s.charAt(0) == " ")) s = s.substring(1,s.length); while(s.length > 0 && (s.charAt(s.length-1) == " ")) s = s.substring(0,s.length - 1); while(s.length > 0 && ((j = s.indexOf(" ")) != -1)) s = s.substring(0,j) + s.substring(j+1,s.length); s = s.split(' '); if(s.length > 0) { n = parseInt(s[0]); if((!isNaN(n)) && (s.length >= n * (n + 1) + 1) && (n <= MAXEQ)) { k = 1; z = true; for(i = 0; i < n; i++) { AB[i] = new Array(n + 1); for(j = 0; j <= n; j++) z = z && !isNaN(AB[i][j] = parseFloat(s[k++])); } if(z) { // Wyświetlamy układ równań t = "<table border='0' cellpadding='4' style='border-collapse: collapse'><tr><td>"; for(i = 0; i < n; i++) { for(j = 0; j <= n; j++) { if(!j) t += AB[i][j]; else if (j == n) t += " = " + AB[i][j]; else t += (AB[i][j] < 0) ? " - " + Math.abs(AB[i][j]) : " + " + AB[i][j]; if(j < n) t += "x<sub>" + (j + 1) + "</sub>"; } t += "<br>"; } t += "</td></tr><tr><td>"; // Obliczamy wyznacznik główny for(i = 0; i < n; i++) WK[i] = i; W = det(n, 0, WK, AB); if(Math.abs(W) < EPS) t += "<font color=red><b>Brak rozwiazania</b></font>"; else { // Obliczamy kolejne wyznaczniki Wi for(i = 0; i < n; i++) { WK[i] = n; // podmieniamy kolumnę współczynnikami bi X[i] = det(n, 0, WK, AB) / W; WK[i] = i; // przywracamy kolumnę współczynników ai } // Wypisujemy wyniki for(i = 0; i < n; i++) t += "x<sub>" + (i + 1) + "</sub> = " + X[i] + "<br>"; t += "</td></tr></table>"; } } } } } document.getElementById("out").innerHTML = t; } </script> </div> </body> </html> |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2025 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.