|
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 |
©2026 mgr Jerzy Wałaszek
|
| SPIS TREŚCI REMANENT |
|
| Podrozdziały |
W poprzednim rozdziale rozwiązaliśmy układ dwóch równań liniowych:
Wyprowadziliśmy wzór na zmienną \(x\):
Wyprowadźmy analogiczny wzór na zmienną \(y\):
Ostatecznie:
Przyjrzyj się tym wzorom. W obu wzorach mianowniki ułamków są tym samym wyrażeniem. Różne są liczniki. Jeśli potraktujemy liczniki i mianowniki tych ułamków jako wyznaczniki macierzy drugiego stopnia, to:
Zapiszmy nasz układ równań w postaci macierzowej:
Macierz \(A\) jest macierzą współczynników stojących przy niewiadomych:
Macierz \(A_x\) powstaje z macierzy \(A\), gdy kolumnę współczynników zmiennej \(x\) zastąpimy macierzą wyrazów wolnych \(B\):
Macierz \(A_y\) powstaje z macierzy \(A\), gdy kolumnę współczynników zmiennej \(y\) zastąpimy macierzą wyrazów wolnych \(B\):
Układ równań posiada rozwiązanie, jeśli wyznacznik macierzy \(A\) jest różny od 0. Wykorzystując wyznaczniki, możemy teraz zapisać:
Wzory, które otrzymaliśmy w poprzednim podrozdziale, nie są przypadkowe. Matematyk szwajcarski Gabriel Cramer pokazał, iż za pomocą wyznaczników można rozwiązywać układy równań liniowych. Są to tak zwane wzory Cramera (ang. Cramer's rule).
Mamy układ \(n\) równań z \(n\) niewiadomymi:
Zapiszmy ten układ równań w postaci macierzowej:
Macierz kwadratowa \(A\) stopnia n jest macierzą współczynników \(a\), które stoją przy niewiadomych \(x\).
Wektor \(X\) jest macierzą niewiadomych \(x\).
Wektor \(B\) jest macierzą współczynników wolnych \(b\).
Oznaczmy przez \(X_i\) macierz, która powstaje z macierzy \(A\) przez zastąpienie wyrazów w kolumnie i-tej wyrazami wektora \(B\):
Wartości zmiennych układu równań obliczamy ze wzorów Cramera:
Układ posiada rozwiązanie, jeśli wyznacznik macierzy współczynników \(A\) jest różny od zera. Jeśli wyznacznik macierzy \(A\) jest równy zero, to układ równań jest albo sprzeczny (nie posiada rozwiązań) , albo nieoznaczony (posiada więcej niż jedno rozwiązanie).
Dla \(n\) niewiadomych \(x\) metoda Cramera wymaga policzenia \({n + 1}\) wyznaczników stopnia \(n\). Powoduje to, iż ma ona klasę złożoności obliczeniowej równą \(O(n^4)\), jeśli wyznaczniki są liczone za pomocą rozkładu LU. Istnieją lepsze metody rozwiązywania układów równań liniowych.
Przykład:
Rozwiązać układ równań:
Układ zapisujemy macierzowo:
Obliczamy wyznacznik macierzy współczynników \(A\). Wykorzystujemy schemat Saurrusa:
Obliczamy wyznacznik macierzy \(X_1\) (macierz A z zamienioną kolumną 1 na macierz B):
Obliczamy wyznacznik macierzy \(X_2\) (macierz A z zamienioną kolumną 2 na macierz B):
Obliczamy wyznacznik macierzy \(X_3\):
Obliczamy niewiadome:
Sprawdzamy, czy wyliczone wartości niewiadomych spełniają równania:
Poniższy program rozwiązuje za pomocą wzorów Cramera układ równań liniowych. Program zawiera funkcję obliczającą wyznacznik macierzy, która wykorzystuje rozkład LU z piwotowaniem. Dane wejściowe do programu wyglądają następująco:
Pierwsza liczba \(n\) określa ilość równań w układzie. Następne \(n\) wierszy po \(n\) liczb definiują współczynniki a przy niewiadomych. Ostatni wiersz zawiera \(n\) liczb definiujących wyrazy wolne \(b\).Układ równań:
|
Dane wejściowe:
5 -1 2 -3 3 5 8 0 7 4 -1 -3 4 -3 2 -2 8 -3 -2 1 2 -2 -1 -6 9 0 56 62 -10 14 28 |
C++// Wzory Cramera
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0066
//---------------------------
#include <iostream>
#include <windows.h>
#include <iomanip>
#include <cmath>
using namespace std;
const double EPS = 0.000000001;
// Funkcja oblicza wartość
// wyznacznika macierzy
// metodą rozkładu LU
// z piwotowaniem
// n - stopień macierzy
// A - wskaźnik macierzy
//----------------------
double det(int n, double ** A)
{
int i, j, k, * W, md, maxw;
double sc, akk, maxe;
// Mnożnik korekcyjny
// dla wyznacznika
md = 1;
// Tworzymy wektor wierszowy
W = new int [n];
// Inicjujemy wektor wierszowy
// numerami wierszy
for(i = 0; i < n; i++)
W[i] = i;
// Rozkład LU
for(k = 0; k < n; k++)
{
// numer wiersza
// z elementem max
maxw = k;
maxe = fabs(A[W[k]][k]);
// Szukamy elementu max
for(i = k + 1; i < n; i++)
if(fabs(A[W[i]][k]) > maxe)
{
maxw = i;
maxe = fabs(A[W[i]][k]);
}
// Jeśli max jest zero,
// to macierz jest
// zdegenerowana
if(maxe <= EPS)
return 0;
// Jeśli max nie leży
// na przekątnej,
// zamieniamy wiersze
if(maxw != k)
{
// Modyfikujemy mnożnik
md = -md;
swap(W[k], W[maxw]);
}
// Dzielnik
akk = A[W[k]][k];
// Normalizujemy kolumnę
for(i = k + 1; i < n; i++)
A[W[i]][k] /= akk;
// Modyfikujemy podmacierz
for(i = k + 1; i < n; i++)
for(j = k + 1; j < n; j++)
A[W[i]][j] -= A[W[i]][k]
* A[W[k]][j];
}
// Obliczamy wyznacznik;
sc = md;
for(k = 0; k < n; k++)
sc *= A[W[k]][k];
delete [] W;
return sc;
}
// Program główny
//---------------
int main()
{
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout << setprecision(5)
<< fixed;
cout
<< "Rozwiązywanie układu "
"równań liniowych "
"wzorami Cramera\n"
"---------------------"
"-----------------"
"---------------\n\n"
"Wpisz dane "
"wejściowe:\n\n";
// Indeksy
int i,j,k;
// Liczba równań w układzie
int n;
cin >> n;
// Tworzymy dynamicznie
// potrzebne macierze
// Macierz współczynników
// przy niewiadomych x
double ** A;
// Macierz pomocnicza
double ** Xi;
A = new double * [n];
Xi = new double * [n];
for(i = 0; i < n; i++)
{
A[i] = new double[n];
Xi[i] = new double[n];
}
// Odczytujemy współczynniki
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
{
cin >> A[i][j];
Xi[i][j] = A[i][j];
}
// Macierz wyrazów wolnych
double * B;
B = new double[n];
// Odczytujemy wyrazy wolne
for(i = 0; i < n; i++)
cin >> B[i];
cout << endl;
// Rozpoczynamy od obliczenia
// wyznacznika macierzy A
double detA = det(n,Xi);
if(fabs(detA)< EPS)
cout <<
"Układ równań nie "
"ma rozwiązania\n";
else
{
// Tworzymy macierz rozwiąń
double * X = new double[n];
// Rozpoczynamy wyliczanie
// niewiadomych
for(k = 0; k < n; k++)
{
// Ustawiamy macierz
// pomocniczą Xi
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if(j == k)
Xi[i][j] = B[i];
else
Xi[i][j] = A[i][j];
// Obliczamy niewiadomą:
X[k] = det(n,Xi) / detA;
}
// Wyświetlamy wyniki:
for(i = 0; i < n; i++)
cout << "x" << i << " = "
<< setw(12)
<< X[i] << endl;
// Usuwamy tablicę
// dynamiczną:
delete [] X;
}
cout << endl;
for(i = 0; i < n; i++)
{
delete [] A[i];
delete [] Xi[i];
}
delete [] A;
delete [] Xi;
delete [] B;
system("pause");
return 0;
}
|
| Wynik |
| Rozwiązywanie układu równań liniowych
wzorami Cramera ----------------------------------------------------- Wpisz dane wejściowe: 5 -1 2 -3 3 5 8 0 7 4 -1 -3 4 -3 2 -2 8 -3 -2 1 2 -2 -1 -6 9 0 56 62 -10 14 28 x0 = 1.00000 x1 = 3.00000 x2 = 5.00000 x3 = 7.00000 x4 = 9.00000 |
Python
(dodatek) # Wzory Cramera
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0066
#---------------------------
EPS = 0.000000001
# Funkcja oblicza wartość
# wyznacznika macierzy
# metodą rozkładu LU
# z piwotowaniem
# n - stopień macierzy
# A - wskaźnik macierzy
#----------------------
def det(n,a):
# Mnożnik korekcyjny
# dla wyznacznika
md = 1
# Tworzymy wektor wierszowy
w = [i for i in range(n)]
# Rozkład LU
for k in range(n):
# numer wiersza
# z elementem max
maxw = k
maxe = abs(a[w[k]][k])
# Szukamy elementu max
for i in range(k + 1, n):
if abs(a[w[i]][k]) > maxe:
maxw = i
maxe = abs(a[w[i]][k])
# Jeśli max jest zero,
# to macierz jest
# zdegenerowana
if(maxe <= EPS):
return 0
# Jeśli max nie leży
# na przekątnej,
# zamieniamy wiersze
if maxw != k:
# Modyfikujemy mnożnik
md = -md
w[k], w[maxw] = w[maxw], w[k]
# Dzielnik
akk = a[w[k]][k]
# Normalizujemy kolumnę
for i in range(k + 1, n):
a[w[i]][k] /= akk
# Modyfikujemy podmacierz
for i in range(k + 1, n):
for j in range(k + 1, n):
a[w[i]][j] -= (a[w[i]][k]
* a[w[k]][j])
# Obliczamy wyznacznik
sc = md
for k in range(n):
sc *= a[w[k]][k]
return sc
# Program główny
#---------------
print("Rozwiązywanie układu "
"równań liniowych "
"wzorami Cramera\n"
"---------------------"
"-----------------"
"---------------\n\n"
"Wpisz dane wejściowe:\n")
n = int(input())
# Tworzymy dynamicznie
# potrzebne macierze
# Odczytujemy współczynniki
# tworząc z nich macierze
a = [[float(s) for s in input().split()]
for _ in range(n)]
xi = [s[:] for s in a]
# Odczytujemy wyrazy wolne
b = [float(s) for s in input().split()]
print()
# Rozpoczynamy od obliczenia
# wyznacznika macierzy A
det_a = det(n,xi)
if abs(det_a) < EPS:
print("Układ równań bez rozwiązania")
else:
# Tworzymy macierz rozwiąń
x = [0.0 for _ in range(n)]
# Rozpoczynamy wyliczanie
# niewiadomych
for k in range(n):
# Ustawiamy macierz
# pomocniczą Xi
for i in range(n):
for j in range(n):
if j == k:
xi[i][j] = b[i]
else:
xi[i][j] = a[i][j];
# Obliczamy niewiadomą:
x[k] = det(n,xi) / det_a
# Wyświetlamy wyniki:
for i in range(n):
print(f"x{i} = {x[i]:12.5f}")
print()
input("Naciśnij Enter...")
|
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 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.