MyMathLib系列(行列式计算)

靠人不如靠己,准备做自己得MathLib,在学校的时候,就想过把数学数理的东西都计算机化,但一直没有时间去做这件事情,现在觉得空余 时间比较闲,就做做这件事情,先从线性代数开始,毕竟这里面的很多算法,实际共走中都有用到。在做这些算法的过程中,也体会到了:数学中的东西不是没有用,而是你没用到。下面的算法(除全排列外)都是自己原创想得,做的不够效率的地方,也请大家分享更好的东西。好了,啰嗦这么多,让代码说话吧:

/// <summary>
    /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见。
    /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过
    /// 严格测试,如需参考,请慎重.
    /// </summary>
    public static partial class LinearAlgebra
    {
        /// <summary>
        /// 求逆序数
        /// </summary>
        /// <param name="Numbers">数字序列</param>
        /// <returns></returns>
        public static int CalcInverseNumber(string Numbers)
        {
            int theRet = 0;
            if (string.IsNullOrWhiteSpace(Numbers))
            {
                return theRet;
            }
            else
            {
                string[] theNumbers = Numbers.Split(new string[] { ",", " " }, StringSplitOptions.RemoveEmptyEntries);
                return CalcInverseNumber(theNumbers);
            }
        }
        /// <summary>
        /// 求逆序数
        /// </summary>
        /// <param name="Numbers">数字序列</param>
        /// <returns></returns>
        public static int CalcInverseNumber(string[] Numbers)
        {
            var theRet = 0;
            if (Numbers.Count() <= 0)
            {
                return theRet;
            }
            else
            {
                string[] theNumbers = Numbers.ToArray();

                int[] theNums = new int[theNumbers.Count()];
                for (int i = 0; i < theNumbers.Count(); i++)
                {
                    theNums[i] = Convert.ToInt32(theNumbers[i]);
                }
                for (int theI = 0; theI < theNums.Count() - 1; theI++)
                {
                    for (int theJ = theI + 1; theJ < theNums.Count(); theJ++)
                    {
                        if (theNums[theI] > theNums[theJ])
                        {
                            theRet++;
                        }
                    }
                }
            }
            return theRet;
        }
        private static string HandlingMultiExp(string Exp, int Sign)
        {
            decimal theRetNum = Sign;
            var theRetLine = "";
            var theDigits = Exp.Split('*');
            foreach (var theD in theDigits)
            {
                decimal theDec = 0;
                if (decimal.TryParse(theD, out theDec))
                {
                    theRetNum *= theDec;
                }
                else
                {
                    if (theRetLine == "")
                    {
                        theRetLine = theD;
                    }
                    else
                    {
                        theRetLine += "*" + theD;
                    }
                }
            }
            if (theRetNum == 0)
            {
                return "";
            }
            else
            {
                if (theRetNum == 1)
                {
                    return theRetLine;
                }
                if (theRetNum == -1)
                {
                    return "-" + theRetLine;
                }
                return theRetNum.ToString() + theRetLine;
            }
        }
        /// <summary>
        /// 行列式表达式展开
        /// </summary>
        /// <param name="Determinants">N阶行列式</param>
        /// <returns></returns>
        public static string DeterminantToExpression(string[,] Determinants)
        {
            int theR = Determinants.GetLength(0);
            int theC = Determinants.GetLength(1);
            if (theR != theC)
            {
                throw new Exception("不是N阶行列式!");
            }
            var theResults = new List<string>();
            List<string> theNs = new List<string>();
            for (int i = 1; i <= theC; i++)
            {
                theNs.Add(i.ToString());
            }
            FullPermutation(theNs, 0, theC - 1, theResults);
            var theNExp = "";
            var thePExp = "";
            foreach (var theAL in theResults)
            {
                var theInverseNum = Convert.ToInt32(Math.Pow(-1, CalcInverseNumber(theAL)));
                var theLine = "";
                string[] theNums = theAL.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 1; i <= theC; i++)
                {
                    var theV = Determinants[i - 1, int.Parse(theNums[i - 1]) - 1];
                    theLine += "*" + theV;
                }
                theLine = HandlingMultiExp(theLine.Substring(1), theInverseNum);
                if (!string.IsNullOrEmpty(theLine))
                {
                    if (theLine[0] == '-')
                    {
                        theNExp += "" + theLine;
                    }
                    else
                    {
                        thePExp += "+" + theLine;
                    }
                }
            }
            return thePExp.Substring(1) + theNExp;
        }
        /// <summary>
        /// 对数组进行全排列
        /// </summary>
        /// <param name="lsArray">要进行全排列的数组</param>
        /// <param name="begin">进行全排列的开始下标</param>
        /// <param name="end">进行全排列的结束下标</param>
        public static void FullPermutation(List<string> lsArray, int begin, int end, List<string> Result)
        {
            if (begin == end)
            {
                string theLine = "";
                for (int i = 0; i <= end; i++)
                {

                    theLine += "," + lsArray[i];
                }
                Result.Add(theLine.Substring(1));
            }

            for (int i = begin; i <= end; i++)
            {
                Swap(lsArray, begin, i);
                FullPermutation(lsArray, begin + 1, end, Result);
                Swap(lsArray, begin, i);
            }

        }
        /// <summary>
        /// 交换数组中的下标为x,y的值
        /// </summary>
        /// <param name="lsArray">该数组</param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private static void Swap(List<string> lsArray, int x, int y)
        {
            string t = lsArray[x];
            lsArray[x] = lsArray[y];
            lsArray[y] = t;
        }
        /// <summary>
        /// 化三角法行列式计算,
        /// </summary>
        /// <param name="Determinants">N阶行列式</param>
        /// <returns>计算结果</returns>
        public static decimal CalcDeterminant(decimal[,] Determinants)
        {
            int theSign = 1;//正负符号,如果需要变换,将记录变换后的符号.
            int theN = Determinants.GetLength(0);
            //从第1列到第theN-1列
            for (int i = 0; i < theN - 1; i++)
            {
                //从第theN-1行到第i+1行,将D[j,i]依次变为0
                for (int j = theN - 1; j > i; j--)
                {
                    //如果为当前值为0,则不处理,继续处理上一行
                    if (Determinants[j, i] == 0)
                    {
                        continue;
                    }

                    //如果[j,i]的上一行[j-1, i]的值为0则交换
                    if (Determinants[j - 1, i] == 0)
                    {
                        //每次交换,行列式的值大小不变,符号取反
                        theSign = 0 - theSign;
                        for (int k = 0; k < theN; k++)
                        {
                            decimal theTmpDec = Determinants[j, k];
                            Determinants[j, k] = Determinants[j - 1, k];
                            Determinants[j - 1, k] = theTmpDec;
                        }
                    }
                    else
                    {
                        //将当前行减去上一行与theRate的积。
                        var theRate = Determinants[j, i] / Determinants[j - 1, i];
                        for (int k = 0; k < theN; k++)
                        {
                            Determinants[j, k] = Determinants[j, k] - Determinants[j - 1, k] * theRate;
                        }
                    }
                }
            }
            //结果为对角线上的元素的乘积,注意符号的处理。
            decimal theRetDec = theSign;
            for (int i = 0; i < theN; i++)
            {
                theRetDec *= Determinants[i, i];
            }
            return theRetDec;
        }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值