在C#中计算NxN矩阵行列式

时间:2010-05-27 15:56:13

标签: c# math matrix determinants

如何计算NxN矩阵C#的行列式?

4 个答案:

答案 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;
    }