MyMathLib系列(行列式计算3)

到今天,行列式和线性方程组部分就完成了。

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

namespace MyMathLib
{

    /// <summary>
    /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见。
    /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过
    /// 严格测试,如需参考,请慎重.
    /// </summary>
    public static partial class LinearAlgebra
    {#region 线性方程组
        /// <summary>
        /// 根据拉普拉斯定理计算行列式值。
        /// </summary>
        /// <param name="Determinants">N阶行列式</param>
        /// <returns>计算结果</returns>
        public static decimal CalcDeterByLaplaceLaw(decimal[,] Determinants)
        {
            var n = Determinants.GetLength(0);
            //如果阶数小于3,则没必要采用拉普拉斯展开
            if (n <= 3)
            {
                return CalcDeterminantAij(Determinants, false);
            }
            var theRows = GetLaplaceRowsOdd(n);
            return CalcDeterByLaplaceLaw(Determinants, theRows);
        }
        /// <summary>
        /// 求解线性方程组,这里要求N
        /// </summary>
        /// <param name="CoefficientDeterminant">线性方程组系数行列式</param>
        /// <param name="ConstantTerms">常数项</param>
        /// <returns></returns>
        public static decimal[] LinearEquations(int UnknownElements,decimal[,] CoefficientDeterminant, decimal[] ConstantTerms)
        {
            var theRowCount = CoefficientDeterminant.GetLength(0);
            var theColCount = CoefficientDeterminant.GetLength(1);
            if (UnknownElements == theRowCount && theColCount == UnknownElements)
            {
                var theD = CalcDeterByLaplaceLaw(CoefficientDeterminant);
                if(theD==0)
                {
                    return null;
                }
                decimal[] theResults = new decimal[UnknownElements];

                for (int i = 1; i <= UnknownElements; i++)
                {
                    //置换第i列,注意保存原来的值,下次计算时恢复
                    var theTemp = new decimal[UnknownElements];
                    for (int j = 1; j <= UnknownElements; j++)
                    {
                        theTemp[j-1] = CoefficientDeterminant[j-1, i-1];
                        CoefficientDeterminant[j - 1, i - 1] = ConstantTerms[j - 1];
                    }
                    var theDi = CalcDeterByLaplaceLaw(CoefficientDeterminant) / theD;
                    theResults[i-1] = theDi;
                    //复原系数行列式.
                    for (int j = 1; j <= UnknownElements; j++)
                    {
                        CoefficientDeterminant[j - 1, i - 1] = theTemp[j - 1];
                    }
                }
                return theResults;

            }
            else
            {
                throw new Exception("参数格式不正确!");
            }
        }
        /// <summary>
        /// 求解线性方程组(消元法),这里与化三角求行列式的方法类似,这里要求方程个数和元个数相同。
        /// 如果方程个数小于元的个数,消元没问题,但涉及到一般解,会牵扯到符号运算,这里暂不考虑.
        /// </summary>
        /// <param name="CoefficientDeterminant">线性方程组系数行列式,最右边N+1列是常数项</param>
        /// <returns></returns>
        public static decimal[] LinearEquationsEM(int UnknownElements,decimal[,] CoefficientDeterminant)
        {
            var theRowCount = CoefficientDeterminant.GetLength(0);
            var theColCount = CoefficientDeterminant.GetLength(1);
            if (UnknownElements == theRowCount && theColCount == UnknownElements + 1)
            {
                decimal[] theResults = new decimal[UnknownElements];
                int theN = UnknownElements;
                //从第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 (CoefficientDeterminant[j, i] == 0)
                        {
                            continue;
                        }

                        //如果[j,i]的上一行[j-1, i]的值为0则交换
                        if (CoefficientDeterminant[j - 1, i] == 0)
                        {
                            for (int k = 0; k <= theN; k++)//这里要交换常数项,所以是k <= theN
                            {
                                decimal theTmpDec = CoefficientDeterminant[j, k];
                                CoefficientDeterminant[j, k] = CoefficientDeterminant[j - 1, k];
                                CoefficientDeterminant[j - 1, k] = theTmpDec;
                            }
                        }
                        else
                        {
                            //将当前行减去上一行与theRate的积。
                            var theRate = CoefficientDeterminant[j, i] / CoefficientDeterminant[j - 1, i];
                            for (int k = 0; k <= theN; k++)//这里要计算常数项,所以是k <= theN
                            {
                                CoefficientDeterminant[j, k] = CoefficientDeterminant[j, k] - CoefficientDeterminant[j - 1, k] * theRate;
                            }
                        }
                    }
                }
                //处理结果
                if (CoefficientDeterminant[UnknownElements - 1, UnknownElements - 1] == 0)
                {
                    if (CoefficientDeterminant[UnknownElements - 1, UnknownElements] == 0)
                    {
                        throw new Exception("无效方程,有无穷个解!");
                    }
                    else
                    {
                        throw new Exception("方程无解!");
                    }
                }
                //结果处理,回代
                for (int i = UnknownElements - 1; i >= 0; i--)
                {
                    //计算已求项
                    decimal theTempDec = 0;
                    for (int j = i + 1; j < theN; j++)
                    {
                        theTempDec += CoefficientDeterminant[i, j] * theResults[j];
                    }
                    //计算结果,如果系数为0,则为无效方程
                    if (CoefficientDeterminant[i, i] == 0)
                    {
                        throw new Exception("无效方程");
                    }
                    theResults[i] = (CoefficientDeterminant[i, UnknownElements] - theTempDec) / CoefficientDeterminant[i, i];
                }
                return theResults;

            }
            else
            {
                throw new Exception("参数格式不正确!");
            }
        }

        #endregion

    }
}
时间: 2024-10-12 19:41:01

MyMathLib系列(行列式计算3)的相关文章

MyMathLib系列(行列式计算)

靠人不如靠己,准备做自己得MathLib: /// <summary> /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见. /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过 /// 严格测试,如需参考,请慎重. /// </summary> public static partial class LinearAlgebra { /// <summary> /// 求逆序数 /// </summary

MyMathLib系列(行列式计算2)

/// <summary> /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见. /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过 /// 严格测试,如需参考,请慎重. /// </summary> public static partial class LinearAlgebra { /// <summary> /// 获取指定i,j的余子式 /// </summary> /// <pa

MyMathLib系列(行列式计算4--向量部分)

1)将向量组进行消元,变换成阶梯矩阵,这是求向量组的极大线性无关组的基本算法.这个方法在前面曾经给出过,但在这里做了改进,目的是为了可以判断是否线性相关: /// <summary> /// 方程组消元,最后一列为系数,结果就在CoefficientDeterminant里. /// 本算法也可以用来求矩阵的秩. /// </summary> /// <param name="CoefficientDeterminant">方程组系数数组</p

MyMathLib系列(订正两个函数)

在行列式消元中的判断条件有问题,这里给出订正后的代码: 1)MyMathLib.LinearAlgebra.CalcDeterminant方法 /// <summary> /// 化三角法行列式计算, /// </summary> /// <param name="Determinants">N阶行列式</param> /// <returns>计算结果</returns> public static double

行列式计算(C#)

最近几天学习高等代数老师说要写个程序算行列式的结果,闲来无事就简单写了一下. 不多说了,上代码 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Nrow_culmn 7 { 8 class Program 9 { 10 public static double jlength = 0; 11 static void Main(st

MyMathLib系列(一元多项式运算求初等因子等)

利用TExp类的运算来求矩阵的特征值,初等因子等: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 一元多项式计算 /// </summary> public class PolynomialOfOneBasic { /// <summary> /// 化成对阶梯矩阵

openstack Juno系列之计算节点搭建

openstack Juno系列之计算节点搭建 nova-compute安装配置 -------------------- apt-get install nova-compute sysfsutils 编辑配置文件 vi /etc/nova/nova.conf [DEFAULT] verbose = True rpc_backend = rabbit rabbit_host = controller rabbit_password = RABBIT_PASS auth_strategy = k

MyMathLib系列(矩阵算法--2)

矩阵相关的算法比较多,也是比较重要的,而且算法之间的性能差异确实比较大,初等变换法求逆比古典法求逆快不是一点点.矩阵的计算量和数值其实都是比较大的,特别是20阶以上,我在机器上最多只搞到40阶,随机产生的矩阵,很容易就爆掉decimal和double类型. 另外,这里使用了操作符重载,后面的一元符号运算也用到了操作符重载,后面如果有时间,我会将这些算法利用这些特性统一起来,本来它们的计算就应该是统一的.特别是符号运算.如果符号运算搞完,还可以试试自动命题证明玩玩. 好了,上矩阵的菜(有点长,但基

MyMathLib系列(向量及矩阵--准备工作)

因为向量和矩阵的计算工作量比较大,为了更好的书写代码,这里增加了几个定义类,这些定义或者扩展方法将在以后的代码中应用到:1.公共枚举类型 /* 文件:PublicEnums.cs * 目的:定义公共枚举类型. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 初等变换类型(课本上是加,这里