Перейти до основного вмісту

Обчислення визначника матриці методом Гаусса

Задача: дано матрицю AA розміру N×NN \times N. Обчислити її визначник.

Коли підходить цей алгоритм?
  • Потрібен визначник числової матриці над дійсними числами (або за модулем), і допустима похибка з рухомою комою?
  • Потрібен точний цілочисловий визначник великих чисел без втрати точності? (якщо так → Метод Краута з довгою арифметикою)
  • Замість визначника потрібно розв'язати систему Ax=bAx=b чи знайти ранг? (система → Метод Гаусса для СЛАР; ранг → Ранг матриці)

Алгоритм

Ми використовуємо ідеї методу Гаусса для розв'язування систем лінійних рівнянь

Ми виконуватимемо ті самі кроки, що й у розв'язуванні систем лінійних рівнянь, за винятком лише ділення поточного рядка на aija_{ij}. Ці операції не змінюватимуть абсолютне значення визначника матриці. Проте, коли ми міняємо місцями два рядки матриці, знак визначника може змінитися.

Застосувавши метод Гаусса до матриці, ми отримуємо діагональну матрицю, визначник якої — це просто добуток елементів на діагоналі. Знак, як уже зазначалося, можна визначити за кількістю переставлених рядків (якщо вона непарна, то знак визначника слід змінити на протилежний). Отже, ми можемо використати алгоритм Гаусса для обчислення визначника матриці зі складністю O(N3)O(N^3).

Слід зауважити, що якщо в якийсь момент ми не знаходимо ненульової клітинки в поточному стовпці, алгоритм має зупинитися і повернути 0.

Реалізація

const double EPS = 1E-9;
int n;
vector < vector<double> > a (n, vector<double> (n));

double det = 1;
for (int i=0; i<n; ++i) {
int k = i;
for (int j=i+1; j<n; ++j)
if (abs (a[j][i]) > abs (a[k][i]))
k = j;
if (abs (a[k][i]) < EPS) {
det = 0;
break;
}
swap (a[i], a[k]);
if (i != k)
det = -det;
det *= a[i][i];
for (int j=i+1; j<n; ++j)
a[i][j] /= a[i][i];
for (int j=0; j<n; ++j)
if (j != i && abs (a[j][i]) > EPS)
for (int k=i+1; k<n; ++k)
a[j][k] -= a[i][k] * a[j][i];
}

cout << det;

Задачі для практики

Відеоматеріали