zoukankan      html  css  js  c++  java
  • 线性代数之行列式的C#研究实现

    最近学习机器学习 才发现以前数学没有学好 开始从线性代数开始学起 读完行列式一章写了些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}	", tarr[m, n]));
                        }
                        sbRs.Append("
    ");
                    }
    
                }
                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();
      
    

      执行结果如下:

  • 相关阅读:
    归类常用控件GroupBox、TabControl、Expander
    ScrollViewer控件
    捕获鼠标位置
    5、标记拓展
    如何实现文件增量同步——算法
    常用的 Nand Flash 指令如下:
    Consistent Hashing算法
    循环冗余检验 (CRC) 算法原理
    yaffs2根文件系统的构建过程
    linux内存管理之uboot第一步
  • 原文地址:https://www.cnblogs.com/devgis/p/7874305.html
Copyright © 2011-2022 走看看