通过 C# 中的未成年人展开计算行列式的递归算法

计算科学 矩阵 数字
2021-12-19 05:41:58

我最近一直在尝试在 C# 中编写一个算法,该算法将使用未成年人的扩展方法通过递归计算矩阵的行列式。我知道还有其他方法,例如上三角和下三角形式,它们可以提供相同的解决方案,但是目前我正试图找出这个问题,并且在试图弄清楚为什么我的程序给我错误时遇到了严重的麻烦几次迭代后未设置对象引用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class MatrixPractice
{

    public class Matrix
    {
        double[,] entries;

        public double[,] Entries
        {
            get {return entries;}
            set {entries = value;}
        }

        public Matrix(int number_of_rows, int number_of_columns)
        {
            Entries = new double[number_of_rows,number_of_columns];
        }

        static public void Print(Matrix A)
        {
            int counter = 0;
            int second_counter = 0;

            for(; counter < A.Entries.GetLength(0); counter++)
            {
                second_counter = 0;

                Console.WriteLine("\n");

                for(; second_counter < A.Entries.GetLength(1); second_counter++)
                {
                    Console.Write(A.Entries[counter, second_counter] + " ");
                }
            }
        }

        static public Matrix Multiply(Matrix A, double b)
        {
            int counter = 0;
            int second_counter = 0;
            Matrix C;

            C = new Matrix(A.Entries.GetLength(0), A.Entries.GetLength(1));

            for(; counter < A.Entries.GetLength(0); counter++)
            {
                second_counter = 0;

                for(; second_counter < A.Entries.GetLength(1); second_counter++)
                {
                    C.Entries[counter, second_counter] = A.Entries[counter, second_counter] * b;
                }
            }

            return C;
        }

        static bool IsDeterminantCalculationPossible(Matrix A)
        {
            if(A.Entries.GetLength(0) == A.Entries.GetLength(1))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    static public int MathPow(int i, int j)
    {
        int counter = 1;
        int multiplier = -1;
        int result = 1;
        int limit = i + j;

        while (counter <= limit)
        {
            result = result * multiplier;
            counter++;
        }

        return result;

    }

    static public double Det(Matrix A)
    {
        double determinant = 0.0;
        double cofactor = 0.0;
        int j = 0;
        Matrix[] Array = new Matrix[A.Entries.GetLength(0)];

        if(IsDeterminantCalculationPossible(A))
        {

            for(; j < A.Entries.GetLength(0); j++)
            {
                Array[j] = new Matrix(A.Entries.GetLength(0) - 1, A.Entries.GetLength(0) - 1);

                if(Array[j].Entries.GetLength(0) > 1)
                {
                    Array[j] = Matrix.Multiply(DeleteRowColumn(A, 0, j), MathPow(1, j+1) * A.Entries[0,j]);

                    cofactor = Det(Array[j]);
                    determinant = determinant + cofactor;
                }
                else
                {
                    Array[j] = Matrix.Multiply(DeleteRowColumn(A, 0, j), MathPow(1, j+1) * A.Entries[0, j]);
                    determinant = determinant + Array[j].Entries[0,0];
                }
            }

            return determinant;
        }
        else
        {
            throw new System.ArgumentException("The matrix must be of the square type before its determinant can be calculated.");
        }
    }

    static void Main() 
    {
        Matrix matrix_a = new Matrix(3,3);

        double determinant = 0.0;

        matrix_a.Entries[0,0] = 5;
        matrix_a.Entries[0,1] = -1;
        matrix_a.Entries[0,2] = 2;
        matrix_a.Entries[1,0] = 4;
        matrix_a.Entries[1,1] = 11;
        matrix_a.Entries[1,2] = 2;
        matrix_a.Entries[2,0] = 5;
        matrix_a.Entries[2,1] = 3;
        matrix_a.Entries[2,2] = 7;

        Matrix.Print(matrix_a);
        Console.WriteLine("\n");

        determinant = Matrix.Det(matrix_a);

        Console.WriteLine("\nDeterminant: {0}", determinant);

        Console.ReadLine();
    }


}

我假设我的算法执行以下操作,当涉及到尺寸大于 1x1 的行列式时,它会通过递归循环,直到计算出 1x1 次要的行列式,然后通过先前的递归反馈,直到它返回主线程计算下一个次要线程,然后重复该过程。

我非常有义务在这件事上寻求帮助,以便有人指出我的错误在哪里。

在上面的代码中,我编写了一个自定义 Matrix 类。我已经测试了 DeleteRowColumn() 方法,它运行良好。但是,Det() 函数给我带来了一些问题。

数学伪代码

Det(A)
    *Create a Loop which Calculates the Cofactors with n Number of
     Cofactors Being Generated in an nxn matrix
             *Initialise an Array of Minors of Dimensions of A_n-1,n-1

             *If the dimensions of the matrix is greater than 1, then
              use the Standard Definition of Determinant Calculation to
              Calculate Determinant which is (-1)^(i+j) * M_i,j
             {
             *Since the Minor is Too Large to have its Determinant Taken,                 
              then Continue Shaving the minor until a Double Value is Achieved

             Therefore: Det(Matrix representing the Minor)

             *Because of Recursion, a Determinant Value Calculated Down the
              Line would be Fed Back Through Former Recursions
              }
              Else
              {
              *Calculate the Cofactor and Add it to a Pre-existing Sum which
               Represents the Final Determinant     
              }
     *EndForLoop
return Determinant

编辑:我意识到我在代码中犯了一些错误,所以我更新了上面的代码。但是,尽管 NullObjectReference 异常现在已经消失,但我没有收到行列式的正确值。根据 SymboLab,它应该是 287,但我得到的是 1621。

1个回答

实际上,我为这个问题困扰社区表示歉意。看起来最终的解决方案实际上很容易。我只是错误地将矩阵元素的乘法放在了未成年人的创造中。它们实际上应该在计算行列式时放置,因为它应该是行列式等于自身加上辅因子乘以适当的矩阵元素。