这里定义的类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()也可以.