如何计算NxN矩阵C#的行列式?
答案 0 :(得分:7)
OP发布another question专门询问4x4矩阵,该矩阵已被关闭,与此问题完全相同。好吧,如果你不是在寻找一般的解决方案,而是仅限于4x4矩阵,那么你可以使用这个看起来很丑陋而又经过验证的代码:
public double GetDeterminant() {
var m = _values;
return
m[12] * m[9] * m[6] * m[3] - m[8] * m[13] * m[6] * m[3] -
m[12] * m[5] * m[10] * m[3] + m[4] * m[13] * m[10] * m[3] +
m[8] * m[5] * m[14] * m[3] - m[4] * m[9] * m[14] * m[3] -
m[12] * m[9] * m[2] * m[7] + m[8] * m[13] * m[2] * m[7] +
m[12] * m[1] * m[10] * m[7] - m[0] * m[13] * m[10] * m[7] -
m[8] * m[1] * m[14] * m[7] + m[0] * m[9] * m[14] * m[7] +
m[12] * m[5] * m[2] * m[11] - m[4] * m[13] * m[2] * m[11] -
m[12] * m[1] * m[6] * m[11] + m[0] * m[13] * m[6] * m[11] +
m[4] * m[1] * m[14] * m[11] - m[0] * m[5] * m[14] * m[11] -
m[8] * m[5] * m[2] * m[15] + m[4] * m[9] * m[2] * m[15] +
m[8] * m[1] * m[6] * m[15] - m[0] * m[9] * m[6] * m[15] -
m[4] * m[1] * m[10] * m[15] + m[0] * m[5] * m[10] * m[15];
}
它假设您将矢量数据存储在一个名为_values
的16个元素数组中(在这种情况下为double
,但float
也可以),按以下顺序:< / p>
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15
答案 1 :(得分:3)
缩小为上三角形,然后形成一个嵌套循环,将位置i == j的所有值相乘。你有它。
答案 2 :(得分:1)
标准方法是LU decomposition。您可能希望使用库而不是自己编码。我不知道C#,但40年的标准是LAPACK。
答案 3 :(得分:1)
此解决方案是使用行操作实现的。我采用了与目标矩阵相同维度的恒等矩阵,然后将目标矩阵转换为恒等矩阵,这样,对目标矩阵执行的每个操作也必须对恒等矩阵执行。最后,目标矩阵将变为恒等矩阵,恒等矩阵将保持目标矩阵的逆矩阵。
private static double determinant(double[,] matrix, int size)
{
double[] diviser = new double[size];// this will be used to make 0 all the elements of a row except (i,i)th value.
double[] temp = new double[size]; // this will hold the modified ith row after divided by (i,i)th value.
Boolean flag = false; // this will limit the operation to be performed only when loop n != loop i
double determinant = 1;
if (varifyRowsAndColumns(matrix, size)) // verifies that no rows or columns are similar or multiple of another row or column
for (int i = 0; i < size; i++)
{
int count = 0;
//this will hold the values to be multiplied by temp matrix
double[] multiplier = new double[size - 1];
diviser[i] = matrix[i, i];
//if(i,i)th value is 0, determinant shall be 0
if (diviser[i] == 0)
{
determinant = 0;
break;
}
/*
* whole ith row will be divided by (i,i)th value and result will be stored in temp matrix.
* this will generate 1 at (i,i)th position in temp matrix i.e. ith row of matrix
*/
for (int j = 0; j < size; j++)
{
temp[j] = matrix[i, j] / diviser[i];
}
//setting up multiplier to be used for multiplying the ith row of temp matrix
for (int o = 0; o < size; o++)
if (o != i)
multiplier[count++] = matrix[o, i];
count = 0;
//for creating 0s at every other position than (i,i)th
for (int n = 0; n < size; n++)
{
for (int k = 0; k < size; k++)
{
if (n != i)
{
flag = true;
matrix[n, k] -= (temp[k] * multiplier[count]);
}
}
if (flag)
count++;
flag = false;
}
}
else determinant = 0;
//if determinant is not 0, (i,i)th element will be multiplied and the result will be determinant
if (determinant != 0)
for (int i = 0; i < size; i++)
{
determinant *= matrix[i, i];
}
return determinant;
}
private static Boolean varifyRowsAndColumns(double[,] matrix, int size)
{
List<double[]> rows = new List<double[]>();
List<double[]> columns = new List<double[]>();
for (int j = 0; j < size; j++)
{
double[] temp = new double[size];
for (int k = 0; k < size; k++)
{
temp[j] = matrix[j, k];
}
rows.Add(temp);
}
for (int j = 0; j < size; j++)
{
double[] temp = new double[size];
for (int k = 0; k < size; k++)
{
temp[j] = matrix[k, j];
}
columns.Add(temp);
}
if (!RowsAndColumnsComparison(rows, size))
return false;
if (!RowsAndColumnsComparison(columns, size))
return false;
return true;
}
private static Boolean RowsAndColumnsComparison(List<double[]> rows, int size)
{
int countEquals = 0;
int countMod = 0;
int countMod2 = 0;
for (int i = 0; i < rows.Count; i++)
{
for (int j = 0; j < rows.Count; j++)
{
if (i != j)
{
double min = returnMin(rows.ElementAt(i), rows.ElementAt(j));
double max = returnMax(rows.ElementAt(i), rows.ElementAt(j));
for (int l = 0; l < size; l++)
{
if (rows.ElementAt(i)[l] == rows.ElementAt(j)[l])
countEquals++;
for (int m = (int)min; m <= max; m++)
{
if (rows.ElementAt(i)[l] % m == 0 && rows.ElementAt(j)[l] % m == 0)
countMod++;
if (rows.ElementAt(j)[l] % m == 0 && rows.ElementAt(i)[l] % m == 0)
countMod2++;
}
}
if (countEquals == size)
{
return false;
// one row is equal to another row. determinant is zero
}
if (countMod == size)
{
return false;
}
if (countMod2 == size)
{
return false;
}
}
}
}
return true;
}
private static double returnMin(double[] row1, double[] row2)
{
double min1 = row1[0];
double min2 = row2[0];
for (int i = 1; i < row1.Length; i++)
if (min1 > row1[i])
min1 = row1[i];
for (int i = 1; i < row2.Length; i++)
if (min2 > row2[i])
min2 = row2[i];
if (min1 < min2)
return min1;
else return min2;
}
private static double returnMax(double[] col1, double[] col2)
{
double max1 = col1[0];
double max2 = col2[0];
for (int i = 1; i < col1.Length; i++)
if (max1 < col1[i])
max1 = col1[i];
for (int i = 1; i < col2.Length; i++)
if (max2 < col2[i])
max2 = col2[i];
if (max1 > max2)
return max1;
else return max2;
}