正文

C#编写的字符串算术表达式计算类2008-07-26 15:57:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/iamben250/37116.html

分享到:

下面是文件的内容,将其全部复制到c#语言下的一个类中即可按上文要求的使用。 ///<author>Emad Barsoum</author>///<email>ebarsoum@msn.com</email>///<date>March 23, 2002</date>///<copyright>///This code is Copyright to Emad Barsoum, it can be used or changed for free without removing the header///information which is the author name, email and date or refer to this information if any change made. ///</copyright>///<summary>///This class <c>Function</c> use the transformation from infix notation to postfix notation to evalute most///Mathematic expression, it support most operators (+,-,*,/,%,^), functions from 0 to any number of parameters///and also a user defined function by using delegate, also it support variables in the expression, it will///generate a symbol table that can be updated at run time.///</summary> using System;using System.Collections; namespace EB.Math{ /// <summary> /// </summary> ///   public enum Type{Variable,Value,UnaryOperator,Operator,Function,Result,Bracket,Comma,Error}  public struct Symbol  {    public string m_name;    public double m_value;    public Type m_type;    public override string ToString()    {      return m_name;    }  }  public delegate Symbol EvaluateFunctionDelegate(string name, params Object[] args); public class Function {    public double Result    {      get      {        return m_result;       }    }     public ArrayList Equation    {      get      {        return (ArrayList)m_equation.Clone();      }    }    public ArrayList Postfix    {      get      {        return (ArrayList)m_postfix.Clone();      }    }     public EvaluateFunctionDelegate DefaultFunctionEvaluation    {      set      {        m_defaultFunctionEvaluation = value;      }    }     public bool Error    {      get      {        return m_bError;      }    }     public string ErrorDescription    {      get      {        return m_sErrorDescription;      }    }  public ArrayList Variables {   get   {    ArrayList var = new ArrayList();    foreach(Symbol sym in m_equation)    {      if((sym.m_type == Type.Variable) && (!var.Contains(sym)))         var.Add(sym);    }    return var;   }   set   {      foreach(Symbol sym in value)      {        for(int i=0;i<m_postfix.Count;i++)        {          if((sym.m_name == ((Symbol)m_postfix[i]).m_name) && (((Symbol)m_postfix[i]).m_type == Type.Variable))          {            Symbol sym1 = (Symbol)m_postfix[i];            sym1.m_value = sym.m_value;            m_postfix[i] = sym1;          }        }      }   } }  public Function() {}     public void Parse(string equation)    {      int state = 1;      string temp = "";      Symbol ctSymbol;       m_bError = false;      m_sErrorDescription = "None";       m_equation.Clear();      m_postfix.Clear();       int nPos = 0;      //-- Remove all white spaces from the equation string --      equation = equation.Trim();      while((nPos=equation.IndexOf(' ')) != -1)        equation = equation.Remove(nPos,1);       for(int i=0;i<equation.Length;i++)      {        switch(state)        {          case 1:            if(Char.IsNumber(equation[i]))            {              state = 2;              temp += equation[i];            }            else if(Char.IsLetter(equation[i]))            {              state = 3;              temp += equation[i];            }            else            {              ctSymbol.m_name = equation[i].ToString();              ctSymbol.m_value = 0;              switch(ctSymbol.m_name)              {                case ",":                  ctSymbol.m_type = Type.Comma;                  break;                case "(":                case ")":                case "[":                case "]":                case "{":                case "}":                  ctSymbol.m_type = Type.Bracket;                  break;                default:                  if(m_equation.Count == 0)                    ctSymbol.m_type = Type.UnaryOperator;                  else if((((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Value) || (((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Variable)                    || (((Symbol)m_equation[m_equation.Count-1]).m_name == ")") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "]") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "}"))                    ctSymbol.m_type = Type.Operator;                  else                    ctSymbol.m_type = Type.UnaryOperator;                  break;              }              m_equation.Add(ctSymbol);            }               break;          case 2:            if((Char.IsNumber(equation[i])) || (equation[i] == '.'))              temp += equation[i];            else if(!Char.IsLetter(equation[i]))            {              state = 1;              ctSymbol.m_name = temp;              ctSymbol.m_value = Double.Parse(temp);              ctSymbol.m_type = Type.Value;              m_equation.Add(ctSymbol);              ctSymbol.m_name = equation[i].ToString();              ctSymbol.m_value = 0;              switch(ctSymbol.m_name)              {                case ",":                  ctSymbol.m_type = Type.Comma;                  break;                case "(":                case ")":                case "[":                case "]":                case "{":                case "}":                  ctSymbol.m_type = Type.Bracket;                  break;                default:                  if(m_equation.Count == 0)                    ctSymbol.m_type = Type.UnaryOperator;                  else if((((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Value) || (((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Variable)                    || (((Symbol)m_equation[m_equation.Count-1]).m_name == ")") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "]") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "}"))                    ctSymbol.m_type = Type.Operator;                  else                    ctSymbol.m_type = Type.UnaryOperator;                  break;              }              m_equation.Add(ctSymbol);              temp = "";            }            break;          case 3:            if(Char.IsLetterOrDigit(equation[i]))              temp += equation[i];            else            {              state = 1;              ctSymbol.m_name = temp;              ctSymbol.m_value = 0;              if(equation[i] == '(')                ctSymbol.m_type = Type.Function;              else              {                if(ctSymbol.m_name == "pi")                  ctSymbol.m_value = System.Math.PI;                else if(ctSymbol.m_name == "e")                  ctSymbol.m_value = System.Math.E;                ctSymbol.m_type = Type.Variable;              }              m_equation.Add(ctSymbol);              ctSymbol.m_name = equation[i].ToString();              ctSymbol.m_value = 0;              switch(ctSymbol.m_name)              {                case ",":                  ctSymbol.m_type = Type.Comma;                  break;                case "(":                case ")":                case "[":                case "]":                case "{":                case "}":                  ctSymbol.m_type = Type.Bracket;                  break;                default:                  if(m_equation.Count == 0)                    ctSymbol.m_type = Type.UnaryOperator;                  else if((((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Value) || (((Symbol)m_equation[m_equation.Count-1]).m_type == Type.Variable)                    || (((Symbol)m_equation[m_equation.Count-1]).m_name == ")") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "]") || (((Symbol)m_equation[m_equation.Count-1]).m_name == "}"))                    ctSymbol.m_type = Type.Operator;                  else                    ctSymbol.m_type = Type.UnaryOperator;                  break;              }              m_equation.Add(ctSymbol);              temp = "";            }            break;        }      }      if(temp != "")      {        ctSymbol.m_name = temp;                if(state == 2)        {          ctSymbol.m_value = Double.Parse(temp);            ctSymbol.m_type = Type.Value;        }        else        {          if(ctSymbol.m_name == "pi")            ctSymbol.m_value = System.Math.PI;          else if(ctSymbol.m_name == "e")            ctSymbol.m_value = System.Math.E;          else            ctSymbol.m_value = 0;          ctSymbol.m_type = Type.Variable;        }        m_equation.Add(ctSymbol);      }    }     public void Infix2Postfix()    {      Symbol tpSym;      Stack tpStack = new Stack();      foreach(Symbol sym in m_equation)      {        if((sym.m_type == Type.Value) || (sym.m_type == Type.Variable))          m_postfix.Add(sym);        else if((sym.m_name == "(") || (sym.m_name == "[") || (sym.m_name == "{"))          tpStack.Push(sym);        else if((sym.m_name == ")") || (sym.m_name == "]") || (sym.m_name == "}"))        {          if(tpStack.Count > 0)          {            tpSym = (Symbol)tpStack.Pop();            while((tpSym.m_name != "(") && (tpSym.m_name != "[") && (tpSym.m_name != "{"))            {              m_postfix.Add(tpSym);              tpSym = (Symbol)tpStack.Pop();            }          }        }        else if(sym.m_type == Type.UnaryOperator)        {          tpStack.Push(sym);        }        else        {          if(tpStack.Count > 0)          {            tpSym = (Symbol)tpStack.Pop();            while((tpStack.Count != 0) && ((tpSym.m_type == Type.UnaryOperator) || (tpSym.m_type == Type.Operator) || (tpSym.m_type == Type.Function) || (tpSym.m_type == Type.Comma)) && (Precedence(tpSym) >= Precedence(sym)))            {              m_postfix.Add(tpSym);              tpSym = (Symbol)tpStack.Pop();               }            if(((tpSym.m_type == Type.UnaryOperator) || (tpSym.m_type == Type.Operator) || (tpSym.m_type == Type.Function) || (tpSym.m_type == Type.Comma)) && (Precedence(tpSym) >= Precedence(sym)))              m_postfix.Add(tpSym);            else              tpStack.Push(tpSym);          }          tpStack.Push(sym);        }      }      while(tpStack.Count > 0)      {        tpSym = (Symbol)tpStack.Pop();        m_postfix.Add(tpSym);      }    }     public void EvaluatePostfix()    {      Symbol tpSym1, tpSym2, tpResult;      Stack tpStack = new Stack();      ArrayList fnParam = new ArrayList();      m_bError = false;      foreach(Symbol sym in m_postfix)      {        if((sym.m_type == Type.Value) || (sym.m_type == Type.Variable) || (sym.m_type == Type.Result))          tpStack.Push(sym);        else if(sym.m_type == Type.UnaryOperator)        {          tpSym1 = (Symbol)tpStack.Pop();          tpResult = Evaluate(sym, tpSym1);          if(tpResult.m_type == Type.Error)          {            m_bError = true;            m_sErrorDescription = tpResult.m_name;            return;          }          tpStack.Push(tpResult);        }        else if(sym.m_type == Type.Operator)        {          tpSym1 = (Symbol)tpStack.Pop();          tpSym2 = (Symbol)tpStack.Pop();          tpResult = Evaluate(tpSym2, sym, tpSym1);          if(tpResult.m_type == Type.Error)          {            m_bError = true;            m_sErrorDescription = tpResult.m_name;            return;          }          tpStack.Push(tpResult);        }        else if(sym.m_type == Type.Comma)        {          tpStack.Push(sym);        }        else if(sym.m_type == Type.Function)        {          fnParam.Clear();          tpSym1 = (Symbol)tpStack.Pop();          if((tpSym1.m_type == Type.Value) || (tpSym1.m_type == Type.Variable) || (tpSym1.m_type == Type.Result))          {            tpResult = EvaluateFunction(sym.m_name,tpSym1);            if(tpResult.m_type == Type.Error)            {              m_bError = true;              m_sErrorDescription = tpResult.m_name;              return;            }            tpStack.Push(tpResult);          }          else if(tpSym1.m_type == Type.Comma)          {            while(tpSym1.m_type == Type.Comma)            {              tpSym1 = (Symbol)tpStack.Pop();              fnParam.Add(tpSym1);              tpSym1 = (Symbol)tpStack.Pop();            }            fnParam.Add(tpSym1);            tpResult = EvaluateFunction(sym.m_name,fnParam.ToArray());            if(tpResult.m_type == Type.Error)            {              m_bError = true;              m_sErrorDescription = tpResult.m_name;              return;            }            tpStack.Push(tpResult);          }          else          {            tpStack.Push(tpSym1);            tpResult = EvaluateFunction(sym.m_name);            if(tpResult.m_type == Type.Error)            {              m_bError = true;              m_sErrorDescription = tpResult.m_name;              return;            }            tpStack.Push(tpResult);          }        }             }      if(tpStack.Count == 1)      {        tpResult = (Symbol)tpStack.Pop();        m_result = tpResult.m_value;      }    }     protected int Precedence(Symbol sym)    {      switch(sym.m_type)      {        case Type.Bracket:          return 7;        case Type.Function:          return 5;        case Type.UnaryOperator:          return 4;        case Type.Comma:          return 0;      }      switch(sym.m_name)      {        case "^":          return 3;        case "/":        case "*":        case "%":          return 2;        case "+":        case "-":          return 1;      }      return -1;    }     protected Symbol Evaluate(Symbol opr, Symbol sym1)    {      Symbol result;      result.m_name = opr.m_name + sym1.m_name;      result.m_type = Type.Result;      result.m_value = 0;      switch(opr.m_name)      {        case "+":          result.m_value = sym1.m_value;;          break;        case "-":          result.m_value = -1 * sym1.m_value;          break;        default:          result.m_type = Type.Error;          result.m_name = "Undefine unary operator: " + opr.m_name + ".";          break;      }      return result;    }     protected Symbol Evaluate(Symbol sym1, Symbol opr, Symbol sym2)    {      Symbol result;      result.m_name = sym1.m_name + opr.m_name + sym2.m_name;      result.m_type = Type.Result;      result.m_value = 0;      switch(opr.m_name)      {        case "^":          result.m_value = System.Math.Pow(sym1.m_value,sym2.m_value);          break;        case "/":        {          if(sym2.m_value != 0)            result.m_value = sym1.m_value / sym2.m_value;          else          {            result.m_name = "Divide by Zero.";            result.m_type = Type.Error;          }          break;        }        case "*":          result.m_value = sym1.m_value * sym2.m_value;          break;        case "%":          result.m_value = sym1.m_value % sym2.m_value;          break;        case "+":          result.m_value = sym1.m_value + sym2.m_value;          break;        case "-":          result.m_value = sym1.m_value - sym2.m_value;          break;        default:          result.m_type = Type.Error;          result.m_name = "Undefine operator: " + opr.m_name + ".";          break;      }      return result;    }     protected Symbol EvaluateFunction(string name, params Object[] args)    {      Symbol result;      result.m_name = "";      result.m_type = Type.Result;      result.m_value = 0;      switch(name)      {        case "cos":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Cos(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "sin":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Sin(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "tan":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Tan(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "cosh":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Cosh(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "sinh":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Sinh(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "tanh":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Tanh(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "log":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Log10(((Symbol)args[0]).m_value);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "ln":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Log(((Symbol)args[0]).m_value,2);          }          else          {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "logn":          if(args.Length == 2)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + "'" + ((Symbol)args[1]).m_value.ToString() + ")";            result.m_value = System.Math.Log(((Symbol)args[0]).m_value,((Symbol)args[1]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "sqrt":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Sqrt(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "abs":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Abs(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "acos":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Acos(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "asin":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Asin(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "atan":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Atan(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        case "exp":          if(args.Length == 1)          {            result.m_name = name + "(" + ((Symbol)args[0]).m_value.ToString() + ")";            result.m_value = System.Math.Exp(((Symbol)args[0]).m_value);          }          else           {            result.m_name = "Invalid number of parameters in: "+ name +".";            result.m_type = Type.Error;          }          break;        default:          if(m_defaultFunctionEvaluation != null)            result = m_defaultFunctionEvaluation(name,args);          else          {            result.m_name = "Function: "+ name +", not found.";            result.m_type = Type.Error;          }          break;      }      return result;    }     protected bool m_bError = false;    protected string m_sErrorDescription = "None";    protected double m_result = 0;    protected ArrayList m_equation = new ArrayList();    protected ArrayList m_postfix = new ArrayList();    protected EvaluateFunctionDelegate m_defaultFunctionEvaluation;  }}

阅读(1722) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册