首页 > 代码库 > MyMathLib系列(一元多项式-准备)

MyMathLib系列(一元多项式-准备)

这里定义的类TExp是基本的计算项,这里的表达式与C#自带的表达式有很大的区别,这里定义这个类主要是为了进行矩阵运算,当然本身也支持普通的运算,但目前不支持除法。这个类目前的用途主要是为了计算矩阵的特征值,特征向量,有时间,再扩展成支持常见的复数域类的数值和符号运算。代码有点长,需要有点耐心:

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

namespace MyMathLib
{
    /// <summary>
    /// 主要用于一元多项式计算,目标是为了求矩阵特征值。
    /// </summary>
    public abstract class TExp
    {
        /// <summary>
        /// 获取A/B的系数比.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <returns></returns>
        public static double GetRelativRation(TExp A, TExp B)
        {
            if (A is TSymbolExp && B is TSymbolExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TSymbolExp)B;
                if (theA.IsZero || theB.IsZero)
                {
                    return 0;
                }
                if (theA.Power == theB.Power)
                {
                    return theA.Ratio / theB.Ratio;
                }
                return 0;

            }
            if (A is TSymbolExp && B is TListExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TListExp)B;
                if (theB.Operands.Count != 1)
                {
                    return 0;
                }
                if (theA.IsZero || theB.IsZero)
                {
                    return 0;
                }
                if (theA.Power == theB.Operands[0].Power)
                {
                    return theA.Ratio / theB.Operands[0].Ratio;
                }
                return 0;
            }
            if (A is TListExp && B is TSymbolExp)
            {
                var theB = (TListExp)A;
                var theA = (TSymbolExp)B;
                if (theB.Operands.Count != 1)
                {
                    return 0;
                }
                if (theA.IsZero || theB.IsZero)
                {
                    return 0;
                }
                if (theA.Power == theB.Operands[0].Power)
                {
                    return theB.Operands[0].Ratio / theA.Ratio;
                }
                return 0;
            }
            var theA1 = (TListExp)A;
            var theB1 = (TListExp)B;
            if (theA1.Operands.Count != theB1.Operands.Count)
            {
                return 0;
            }
            var thePreRate = 0.0;
            for (int i = 0; i < theA1.Operands.Count; i++)
            {
                var theA = theA1.Operands[i];
                var theB = theB1.Operands[i];
                if (theA.IsZero || theB.IsZero)
                {
                    return 0;
                }
                if (theA.Power == theB.Power)
                {
                    var theRate = theA.Ratio / theB.Ratio;
                    if (thePreRate.IsEqualTo(0))
                    {
                        thePreRate = theRate;
                    }
                    else
                    {
                        if (!(thePreRate -theRate).IsEqualTo(0))
                        {
                            return 0;
                        }
                    }
                }
                else
                {
                    return 0;
                }
            }
            return thePreRate;
        }
        /// <summary>
        /// 获取最高次项的系数
        /// </summary>
        /// <returns></returns>
        public abstract double GetMaxPowerItemRatio();
        public abstract bool IsConstance{get;}
        public abstract bool IsNotZeroConst { get; }
        public abstract bool IsZero{get;}
         public TSymbolExp GetMaxPowerExp()
        {
            if (this is TSymbolExp)
            {
                return (TSymbolExp)this;
            }
            TListExp theExp= (TListExp)this;
            if (theExp.Operands.Count > 0)
            {
                return theExp.Operands[theExp.Operands.Count-1];
            }
            return 0;
        }

        public abstract string GetExpString();
        public static TExp NewSymbolElement(string Symbol)
        {
            return new TSymbolExp() { Power = 1, Ratio = 1, Symbol = Symbol };
        }

        public static TExp operator *(TExp A, TExp B)
        {
            if (A is TSymbolExp && B is TSymbolExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TSymbolExp)B;
                return theA * theB;

            }
            if (A is TSymbolExp && B is TListExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TListExp)B;
                return theA * theB;
            }
            if (B is TSymbolExp && A is TListExp)
            {
                var theA = (TListExp)A;
                var theB = (TSymbolExp)B;
                return theA * theB;
            }
            var theA1 = (TListExp)A;
            var theB1 = (TListExp)B;
            return theA1 * theB1;
        }

        public static TExp operator +(TExp A, TExp B)
        {
            if (A is TSymbolExp && B is TSymbolExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TSymbolExp)B;
                return theA + theB;

            }
            if (A is TSymbolExp && B is TListExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TListExp)B;
                return theA + theB;
            }
            if (B is TSymbolExp && A is TListExp)
            {
                var theA = (TListExp)A;
                var theB = (TSymbolExp)B;
                return theB + theA;
            }
            var theA1 = (TListExp)A;
            var theB1 = (TListExp)B;
            return theA1 + theB1;
        }

        public static TExp operator -(TExp B)
        {
            return -1 * B;
        }
        public static TExp operator -(TExp A, TExp B)
        {
            var theB = -B;
            return A + theB;
        }

        public static bool operator ==(TExp A, TExp B)
        {
            if (A is TSymbolExp && B is TSymbolExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TSymbolExp)B;
                return theA == theB;

            }
            if (A is TSymbolExp && B is TListExp)
            {
                var theA = (TSymbolExp)A;
                var theB = (TListExp)B;
                return theA == theB;
            }
            if (B is TSymbolExp && A is TListExp)
            {
                var theA = (TListExp)A;
                var theB = (TSymbolExp)B;
                return theA == theB;
            }
            var theA1 = (TListExp)A;
            var theB1 = (TListExp)B;
            return theA1 == theB1;
        }
        public static bool operator !=(TExp A, TExp B)
        {
            return !(A == B);
        }

        public static bool operator ==(TExp A, double B)
        {
            if (A is TSymbolExp)
            {
                return A == B;

            }

            if (A is TListExp)
            {
                return A == B;
            }
            return false;
        }
        public static bool operator !=(TExp A, double B)
        {
            return !(A == B);
        }

        public static bool operator ==(double A, TExp B)
        {
            return B == A;
        }
        public static bool operator !=(double A, TExp B)
        {
            return !(B == A);
        }

        public static implicit operator TExp(double A)
        {
            return (TSymbolExp)A;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (obj is TExp)
            {
                return this == (TExp)obj;
            }
            return false;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
    /// <summary>
    /// 符号项,也是基本项,Power=0,就是普通数值项。
    /// </summary>
    public class TSymbolExp : TExp
    {
       
        public UInt32 Power { get; set; }
        public string Symbol { get; set; }
        public double Ratio { get; set; }
        public override string GetExpString()
        {
            return GetExpString(true);
        }

        public string GetExpString(bool IsSingle)
        {
            if (Ratio.IsEqualTo(0))
            {
                if (IsSingle)
                {
                    return "0";
                }
                return "";
            }
            var theSign = "-";
            var theRatio = Math.Abs(this.Ratio).ToString("0.######");
            var theSymbol = Symbol;
            var thePower = "^" + Power;
            if (Ratio > 0)
            {
                if (IsSingle)
                {
                    theSign = "";
                }
                else
                {
                    theSign = "+";
                }
            }
            if (Math.Abs(this.Ratio).IsEqualTo(1))
            {
                theRatio = "";
            }
            if (Power == 0)
            {
                theSymbol = "";
                thePower = "";
                theRatio = Math.Abs(this.Ratio).ToString();
            }
            else if (Power == 1)
            {
                thePower = "";
            }
            return theSign + theRatio + theSymbol + thePower;
        }



        public static TSymbolExp operator *(TSymbolExp A, TSymbolExp B)
        {
            var theNewExp = new TSymbolExp();
            theNewExp.Symbol = A.Symbol;
            if(string.IsNullOrEmpty(theNewExp.Symbol))
            {
                theNewExp.Symbol = B.Symbol;
            }
            if (A.Ratio.IsEqualTo(0) || B.Ratio.IsEqualTo(0))
            {
                theNewExp.Ratio = 0;
                theNewExp.Power = 0;
                theNewExp.Symbol = "";
                return theNewExp;
            }
            theNewExp.Ratio = A.Ratio * B.Ratio;
            theNewExp.Power = A.Power + B.Power;
            if (theNewExp.Ratio.IsEqualTo(0))
            {
                theNewExp.Ratio = 0;
                theNewExp.Power = 0;
                theNewExp.Symbol = "";
            }
            return theNewExp;
        }

        public static TSymbolExp operator *(TSymbolExp A, double B)
        {
            if (B.IsEqualTo(0))
            {
                return new TSymbolExp() { Ratio = 0, Power = 0, Symbol = "" };
            }
            return new TSymbolExp() { Ratio = B * A.Ratio, Power = A.Power, Symbol = A.Symbol };
        }
        public static TSymbolExp operator *(double A, TSymbolExp B)
        {
            return B * A;
        }

        public static TExp operator +(TSymbolExp A, double B)
        {
            if (B.IsEqualTo(0))
            {
                return A;
            }
            var theB = new TSymbolExp() { Ratio = B, Power = 0,Symbol=""};
            return A + theB;
        }
        public static TExp operator +(double A, TSymbolExp B)
        {
            if (A.IsEqualTo(0))
            {
                return B;
            }
            return B + A;
        }
        public static TExp operator +(TSymbolExp A, TSymbolExp B)
        {
            if (A.Power == B.Power && (A.Symbol == B.Symbol 
                || string.IsNullOrEmpty(A.Symbol) == string.IsNullOrEmpty(B.Symbol)))
            {
                var theNewExp = new TSymbolExp();
                theNewExp.Symbol = A.Symbol ?? B.Symbol;
                theNewExp.Ratio = A.Ratio + B.Ratio;
                theNewExp.Power = A.Power;
                if (theNewExp.Ratio.IsEqualTo(0))
                {
                    theNewExp.Ratio = 0;
                    theNewExp.Power = 0;
                    theNewExp.Symbol = "";
                }
                return theNewExp;
            }
            else
            {
                var theNewExp = new TListExp();
                if (A.Power < B.Power)
                {
                    theNewExp.Operands.Add(A);
                    theNewExp.Operands.Add(B);
                }
                else
                {
                    theNewExp.Operands.Add(B);
                    theNewExp.Operands.Add(A);
                }
                return theNewExp;
            }


        }
        public static bool operator ==(TSymbolExp A, TSymbolExp B)
        {
            return (A.Ratio == B.Ratio && A.Power == B.Power && (A.Symbol == B.Symbol
                || string.IsNullOrEmpty(A.Symbol) == string.IsNullOrEmpty(B.Symbol)));
        }
        public static bool operator !=(TSymbolExp A, TSymbolExp B)
        {
            return !(A == B);
        }
        public static bool operator ==(TSymbolExp A, double B)
        {
            return (A.Ratio == B && A.Power == 0);
        }
        public static bool operator !=(TSymbolExp A, double B)
        {
            return !(A == B);
        }
        public static bool operator !=(double A, TSymbolExp B)
        {
            return !(B == A);
        }
        public static bool operator ==(double A, TSymbolExp B)
        {
            return (B == A);
        }
        public static implicit operator double(TSymbolExp A)
        {
            if (A.Power == 0)
            {
                return A.Ratio;
            }
            throw new Exception("非常数项,不能转换!");
        }
        public static implicit operator TSymbolExp(double A)
        {
            return new TSymbolExp() { Ratio = A, Power = 0 };
        }

       
        public TSymbolExp Clone()
        {
            return new TSymbolExp() { Power = this.Power, Ratio = this.Ratio, Symbol = this.Symbol };
        }
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (obj is TSymbolExp)
            {
                return ((TSymbolExp)obj == this);
            }
            return false;
        }
        public override int GetHashCode()
        {
            return (this.GetType().Name + this.Power.ToString()
                + this.Ratio.ToString()
                + this.Symbol.ToString()).GetHashCode();
        }
        public override string ToString()
        {
            return GetExpString();
        }

        public override bool IsConstance
        {
            get
            {
                return this.Power == 0;
            }
        }

        public override bool IsZero
        {
            get {
                return this.Ratio.IsEqualTo(0);
            }
        }

        public override bool IsNotZeroConst
        {
            get {
                return this.Power == 0 && this.Ratio != 0;
            }
        }

        public override double GetMaxPowerItemRatio()
        {
            return this.Ratio;
        }
    }

    /// <summary>
    /// 项积,因为任何符号表达式都可以表达成项积的和.
    /// </summary>
    public class TListExp : TExp
    {
        public List<TSymbolExp> Operands { get; set; }
        public TListExp()
        {
            Operands = new List<TSymbolExp>();
        }
        public override string GetExpString()
        {
            var theRet = "";
            if (Operands.Count == 0)
            {
                return "0";
            }
            if (Operands.Count == 1)
            {
                return Operands[0].GetExpString(true); 
            }
            for (int i = Operands.Count - 1; i >= 0; i--)
            {
                theRet = theRet + Operands[i].GetExpString(false);
            }
            if (theRet.Length > 0)
            {
                if (theRet[0] == ‘+‘)
                {
                    theRet = theRet.Substring(1);
                }
            }
            return theRet;
        }
        public static TExp operator +(TListExp A, TSymbolExp B)
        {
            var theRet = new TListExp();
            if (B.Ratio.IsEqualTo(0))
            {
                theRet.Operands.AddRange(A.Operands);
                return theRet;
            }
            var theHasInserted = false;
            for (int i = 0; i < A.Operands.Count; i++)
            {
                if (B.Power == A.Operands[i].Power)
                {
                    var theNewExp = (TSymbolExp)(B + A.Operands[i]);
                    if (!theNewExp.Ratio.IsEqualTo(0))
                    {
                        theRet.Operands.Add(theNewExp);
                    }
                    continue;
                }
                if (B.Power > A.Operands[i].Power)
                {
                    if (theHasInserted == false)
                    {
                        A.Operands.Add(B);
                        theHasInserted = true;
                    }
                }
                theRet.Operands.Add(A.Operands[i]);
            }
            return theRet;
        }
        public static TExp operator +(TSymbolExp A, TListExp B)
        {
            return B + A;
        }
        public static TListExp operator +(TListExp A, TListExp B)
        {
            TListExp theRet = new TListExp();
            int theAi = 0;
            int theBi = 0;
            while (theAi < A.Operands.Count && theBi < B.Operands.Count)
            {
                if (A.Operands[theAi].Power == B.Operands[theBi].Power)
                {
                    var theTemp = (TSymbolExp)(A.Operands[theAi] + B.Operands[theBi]);
                    if (!theTemp.Ratio.IsEqualTo(0))
                    {
                        theRet.Operands.Add(theTemp);
                    }
                    theAi++;
                    theBi++;
                    continue;
                }
                if (A.Operands[theAi].Power < B.Operands[theBi].Power)
                {
                    theRet.Operands.Add(A.Operands[theAi]);
                    theAi++;
                    continue;
                }
                theRet.Operands.Add(B.Operands[theBi]);
                theBi++;
            }
            for (int i = theAi; i < A.Operands.Count; i++)
            {
                theRet.Operands.Add(A.Operands[i]);
            }
            for (int i = theBi; i < B.Operands.Count; i++)
            {
                theRet.Operands.Add(B.Operands[i]);
            }
            return theRet;
        }

        public static TListExp operator *(TListExp A, TSymbolExp B)
        {
            var theRet = new TListExp();
            for (int i = 0; i < A.Operands.Count; i++)
            {
                var theTmp = A.Operands[i] * B;
                if (!theTmp.Ratio.IsEqualTo(0))
                {
                    theRet.Operands.Add(theTmp);
                }
            }
            return theRet;
        }
        public static TListExp operator *(TSymbolExp A, TListExp B)
        {
            return B * A;
        }
        public static TListExp operator *(TListExp A, TListExp B)
        {
            var theRet = new TListExp();
            for (int i = 0; i < A.Operands.Count; i++)
            {
               var theTmp = A.Operands[i] * B;
               theRet = theRet + theTmp;
            }
            return theRet;
        }

        public static TListExp operator *(TListExp A, double B)
        {
            if (B.IsEqualTo(0))
            {
                return A;
            }
            var theB = new TSymbolExp() { Ratio = B, Power = 0 };
            return A * theB;
        }
        public static TListExp operator *(double A, TListExp B)
        {
            return B * A;
        }

        public static TExp operator +(TListExp A, double B)
        {
            if (B.IsEqualTo(0))
            {
                return A;
            }
            var theB = new TSymbolExp() { Ratio = B, Power = 0 };
            return A + theB;
        }
        public static TExp operator +(double A, TListExp B)
        {
            if (A.IsEqualTo(0))
            {
                return B;
            }
            return B + A;
        }

        public static bool operator ==(TListExp A, TListExp B)
        {

            bool theRet = true;
            for (int i = 0; i < A.Operands.Count && i < B.Operands.Count; i++)
            {
                if (A.Operands[i] != B.Operands[i])
                {
                    theRet = false;
                    break;
                }
            }
            return theRet;
        }
        public static bool operator !=(TListExp A, TListExp B)
        {
            return !(A == B);
        }

        public static bool operator ==(TListExp A, TSymbolExp B)
        {
            switch (A.Operands.Count)
            {
                case 0:
                    return B == (TSymbolExp)0;
                case 1:
                    return A.Operands[0] == B;
            }
            return false;
        }
        public static bool operator !=(TListExp A, TSymbolExp B)
        {
            return !(A == B);
        }
        public static bool operator ==(TSymbolExp A, TListExp B)
        {
            return (B == A);
        }
        public static bool operator !=(TSymbolExp A, TListExp B)
        {
            return !(B == A);
        }
        public static bool operator ==(TListExp A, double B)
        {
            bool theRet = true;
            if (A.Operands.Count > 1)
            {
                theRet = false;
            }
            else
            {
                theRet = A.Operands[0] == B;
            }
            return theRet;
        }
        public static bool operator !=(TListExp A, double B)
        {
            return !(A == B);
        }
        public static bool operator ==(double A, TListExp B)
        {
            return (B == A);
        }
        public static bool operator !=(double A, TListExp B)
        {
            return !(B == A);
        }
        public static implicit operator double(TListExp A)
        {
            if (A.Operands.Count == 1)
            {
                return A.Operands[0];
            }
            throw new Exception("不能转换!");
        }
        public static implicit operator TListExp(double A)
        {
            TSymbolExp theA = A;
            var theRet = new TListExp();
            theRet.Operands.Add(theA);
            return theRet;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            return this == (TListExp)obj;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override string ToString()
        {
            return GetExpString();
        }

        /// <summary>
        /// 是否是数值
        /// </summary>
        public override bool IsConstance
        {
            get {
                return this.Operands.Count == 1 && this.Operands[0].Power == 0 || this.Operands.Count == 0;
            }
        }

        public override bool IsZero
        {
            get {
                return this.Operands.Count == 0;
            }
        }

        public override bool IsNotZeroConst
        {
            get {
                return this.Operands.Count == 1 && this.Operands[0].Power == 0 && this.Operands[0].Ratio != 0;
            }
        }
        /// <summary>
        /// 获取最高次项的系数
        /// </summary>
        /// <returns></returns>
        public override double GetMaxPowerItemRatio()
        {
            if (this.Operands.Count==0)
            {
                return 0;
            }
            return this.Operands[this.Operands.Count - 1].Ratio;
        }
    }
}


简单的用法:

TExp x = new TSymbolExp() { Power = 1, Ratio = 1, Symbol = "x" };
 var theA = (x - 7) * (x - 7) * (x - 1);

答案可以自己测试。显示的时候只要调用GetExpString().ToString()也可以.

MyMathLib系列(一元多项式-准备)