まず、n*n行列Aの行列式は、
上の定義より、n*n行列の行列式をそのまま計算すると、O(n*n!)の計算量が必要となってしまう。大きなサイズ(n>20)の行列の行列式を簡単に計算するために、以下の性質を用いる。
行列Aのi行から、j行の定数倍を引いても、行列式の値は変わらない。
上記の性質を使って行列Aを上三角行列に変更する。行列式の定義を見ると、上三角行列の行列式は、対角成分の積と等しいことに気付く。
三角行列への変換はO(n^3)、対角成分の積を求める処理はO(n)なので、全体でO(n^3)の計算量で行列式を求めることができる。
以下サンプルソース。
const int N = 3;
double determinant(const double x[][N]) {
double tmp[N][N];
memcpy(tmp, x, sizeof(tmp));
// make pivots non-zero numbers
for (int i = 0; i < N; i++) {
if (tmp[i][i] != 0)
continue;
int k;
for (k = 0; k < N; k++)
if (tmp[k][i] != 0)
break;
if (k == N) // all numbers in a column is zero
return 0;
for (int j = 0; j < N; j++)
tmp[i][j] += tmp[k][j];
}
// make a triangular matrix
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i == j)
continue;
double c = tmp[j][i] / tmp[i][i];
for (int k = 0; k < N; k++)
tmp[j][k] -= c * tmp[i][k];
}
}
double det = 1;
for (int i = 0; i < N; i++)
det *= tmp[i][i];
return det;
}
int main() {
double x[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
x[i][j] = -50 + rand() % 100;
}
cout << determinant(x) << endl;
return 0;
}
0 件のコメント:
コメントを投稿