1. 程式人生 > >線性代數之行列式的C#研究實現

線性代數之行列式的C#研究實現

學習 ops {0} builder att interop turn gen new

最近學習機器學習 才發現以前數學沒有學好 開始從線性代數開始學起 讀完行列式一章寫了些C#的代碼學習一下。

直接上C#代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace LYF.Math
{
    /// <summary>
    /// 行列式 Determinant
    /// </summary>
    [SerializableAttribute]
    [ComVisibleAttribute(true)]
    public class Determinant<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
    {
        T[,] tarr = null;
        public Determinant(int n)
        {
            tarr = new T[n, n];
        }

        public Determinant(T[,] arrT)
        {
            if (arrT == null || arrT.GetLength(0) != arrT.GetLength(1) || arrT.GetLength(0) < 1)
            {
                throw new MathException("不正確的數組(數組必須行列數相同且大於1)");
            }
            else
            {
                tarr=new T[arrT.GetLength(0),arrT.GetLength(0)];
                SetItem(arrT);
            }
        }

        /// <summary>
        /// 獲取元素值
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        public T this[int i, int j]
        {
            //實現索引器的get方法
            get
            {
                return GetItem(i, j);
            }

            //實現索引器的set方法
            set
            {
                SetItem(i, j, value);
            }
        }

        /// <summary>
        /// 獲取元素的余子式
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        public Determinant<T> A(int i, int j)
        {
            if (N == 1)
            {
                return null;
            }
            else if (i>N||j>N)
            {
                return null;
            }
            else
            {
                Determinant<T> a = new Determinant<T>(N - 1);
                for (int m = 1; m <= N - 1; m++)
                {
                    for (int n = 1; n <= N - 1; n++)
                    {
                        int p = m, q = n;
                        if (p >= i)
                        {
                            p = m + 1;
                        }
                        if (q >= j)
                        {
                            q = n + 1;
                        }
                        a[m, n] = this[p,q];
                    }
                }
                return a;
            }
        }


        /// <summary>
        /// 設置行列式的值
        /// </summary>
        /// <param name="i">行數(從1開始)</param>
        /// <param name="j">列數(從1開始)</param>
        /// <param name="value">值</param>
        public void SetItem(int i, int j, T value)
        {
            if (tarr == null)
            {
                throw new MathException("行列式未正確初始化");
            }
            else if (i > N || j > N)
            {
                throw new MathException("超出行列式索引範圍");
            }
            else
            {
                tarr[i - 1, j - 1] = value;
            }
        }

        public void SetItem(T[,] arrT)
        {
            if (arrT == null || tarr == null)
            {
                throw new MathException("不能為空");
            }
            else if (arrT.GetLength(0) != N || arrT.GetLength(1) != N)
            {
                throw new MathException("傳入階數不同");
            }
            else
            {
                for (int m = 0; m <=N-1; m++)
                {
                    for (int n = 0; n <= N- 1; n++)
                    {
                        this[m + 1, n + 1] = arrT[m, n];
                    }
                }
            }
        }

        /// <summary>
        /// 設置行列式的值
        /// </summary>
        /// <param name="i">行數(從1開始)</param>
        /// <param name="j">列數(從1開始)</param>
        /// <param name="value">值</param>
        public T GetItem(int i, int j)
        {
            if (tarr == null)
            {
                throw new MathException("行列式未正確初始化");
            }
            else if (i > N || j > N)
            {
                throw new MathException("超出行列式索引範圍");
            }
            else
            {
                return tarr[i-1, j-1];
            }
        }

        /// <summary>
        /// 輸出行列式信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder sbRs = new StringBuilder();
            if(tarr!=null)
            {
                for (int m = 0; m <= N - 1; m++)
                {
                    for (int n = 0; n <= N - 1; n++)
                    {
                        sbRs.Append(string.Format("{0}\t", tarr[m, n]));
                    }
                    sbRs.Append("\n");
                }

            }
            return sbRs.ToString();
        }

        /// <summary>
        /// 獲取行列式的階數
        /// </summary>
        public int N
        {
            get{
                if (tarr != null)
                {
                    return tarr.GetLength(0);
                }
                else
                {
                    return 0;
                }
            }
            
        }


        private string typeName = string.Empty;
        private string GetType()
        {
            if (string.IsNullOrEmpty(typeName))
            {
                typeName=typeof(T).Name;
                File.AppendAllText("E:\\op.txt", typeName);
            }
            return typeName;

        }

        /// <summary>
        /// 獲取行列式的值
        /// </summary>
        public T Value
        {
            get
            {
                if (N == 1)
                {
                    return tarr[0, 0];
                }
                else if (N == 2)
                {
                    return Minus(MUL(tarr[0, 0], tarr[1, 1]), MUL(tarr[0, 1], tarr[1, 0]));
                }
                else
                {
                    T sum = default(T);
                    for (int i = 1; i <= N; i++)
                    {
                        if ((1+i) % 2 == 0)
                        {
                            //余子式正值
                            sum = Add(sum, MUL(this[1, i], this.A(1, i).Value));
                        }
                        else
                        {
                            //余子式負值
                            sum = Minus(sum, MUL(this[1, i], this.A(1, i).Value));
                        }
                    }
                    return sum;
                }
                
            }
        }

        /// <summary>
        /// 加法
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        private T Add(T left, T right)
        {
            switch (GetType())
            {
                case "Int16":
                    return ((T)(object)((short)(object)left + (short)(object)right));
                case "Int32":
                    return ((T)(object)((int)(object)left + (int)(object)right));
                case "Int64":
                    return ((T)(object)((long)(object)left + (long)(object)right));
                case "Single":
                    return ((T)(object)((float)(object)left + (float)(object)right));
                case "Double":
                    return ((T)(object)((double)(object)left + (double)(object)right));
                case "Decimal":
                    return ((T)(object)((decimal)(object)left + (decimal)(object)right));
            }
            throw new MathException("不支持的操作類型");
        }

        /// <summary>
        /// 減法
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        private T Minus(T left, T right)
        {
            switch (GetType())
            {
                case "Int16":
                    return ((T)(object)((short)(object)left - (short)(object)right));
                case "Int32":
                    return ((T)(object)((int)(object)left - (int)(object)right));
                case "Int64":
                    return ((T)(object)((long)(object)left - (long)(object)right));
                case "Single":
                    return ((T)(object)((float)(object)left - (float)(object)right));
                case "Double":
                    return ((T)(object)((double)(object)left - (double)(object)right));
                case "Decimal":
                    return ((T)(object)((decimal)(object)left - (decimal)(object)right));
            }
            throw new MathException("不支持的操作類型");
        }

        /// <summary>
        /// 乘法
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        private T MUL(T left, T right)
        {
            switch (GetType())
            {
                case "Int16":
                    return ((T)(object)((short)(object)left * (short)(object)right));
                case "Int32":
                    return ((T)(object)((int)(object)left * (int)(object)right));
                case "Int64":
                    return ((T)(object)((long)(object)left * (long)(object)right));
                case "Single":
                    return ((T)(object)((float)(object)left * (float)(object)right));
                case "Double":
                    return ((T)(object)((double)(object)left * (double)(object)right));
                case "Decimal":
                    return ((T)(object)((decimal)(object)left * (decimal)(object)right));
            }
            throw new MathException("不支持的操作類型");
        }


    }
}

  以上代碼就是對行列式的封裝 可以求值獲得余子式 很基本的東西 求值的話主要用了遞歸的方式 因為泛型的原因導致計算過程重復拆箱裝箱 不過目前好像也沒有什麽太好的方法了。反正就是學習 所以性能無所謂了。

然後就是調用了直接上調用代碼:

            int[,] aaa = new int[4, 4]{{1,2,3,6},
                                        {4,5,7,8},
                                        {7,8,9,10},
                                        {3,8,4,3}};

            //LYF.Math.Determinant<int> d = new Determinant<int>(4);
            LYF.Math.Determinant<int> d = new Determinant<int>(aaa);
            d.SetItem(aaa);
            Console.WriteLine("當前行列式:");
            Console.WriteLine(d.ToString());
            Console.WriteLine("余子式M11:");
            Console.WriteLine(d.A(1, 1).ToString());
            Console.WriteLine("余子式M12:");
            Console.WriteLine(d.A(1, 2).ToString());
            Console.WriteLine("余子式M22:");
            Console.WriteLine(d.A(2, 2).ToString());
            Console.WriteLine("N="+d.N);
            Console.WriteLine("行列式的值為:"+d.Value.ToString());
            Console.Read();
  

  執行結果如下:

技術分享圖片

線性代數之行列式的C#研究實現