标签:
这里定义的类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);
标签:
原文地址:http://blog.csdn.net/hawksoft/article/details/42501047