目前我有个需求,要求取得给定字符串计算后的数值。如 "20+3*5-10/2.5" 将返回 31
表达式中可能出现的运算符号包括 + - × /
暂不考虑括号及符号还有其它特殊运算符,但会有小数

解决方案 »

  1.   

    private const char EndChar = ';';
    private const char Inter_Minus = '#';//内部负号
    private const char FlagChar = '$';
    private static readonly char[] InvalidChars = new char[] {EndChar, Inter_Minus, FlagChar};
    private static readonly char[] Symbols = new char[] {'*','/','+','-','(',')'}; 
    private static readonly char[] Symbols_Simple = new char[] {'*','/','+','-',EndChar};public static double EvaluateSimpleExpression(string expression)
    {
    double result = 0;//结果
    double data = 0;//中间结果
    string dataStr;
    char opera,topopera;
    int index;
    ArrayList NS = new ArrayList();  //数栈
    ArrayList OS = new ArrayList();  //运算符栈 expression += EndChar;
    if (expression[0] == '-' || expression[0] == '+')
    expression = "0" + expression; while ((index = expression.IndexOfAny(Symbols_Simple)) != -1)
    {
    if(index != 0)  //数据
    {
    try
    {
    dataStr = expression.Substring(0,index);
    if (dataStr[0] == Inter_Minus) dataStr = "-"+dataStr.Remove(0, 1);
    data = double.Parse(dataStr);
    NS.Add(data);
    expression = expression.Substring(index,expression.Length-index);
    }
    catch (Exception ec)
    {
    throw new Exception("表达式中有不能识别的字符。", ec);
    }
    }
    else //运算符
    {
    try
    {
    opera = expression[index];
    if (OS.Count == 0)
    {
    if (opera == EndChar)
    result = (double)NS[NS.Count-1];
    else
    OS.Add(opera);
    }
    else
    {
    topopera = (char)OS[OS.Count-1];
    while ((topopera == '*' || topopera == '/') ||
    ((topopera == '+' || topopera == '-') && (opera != '*' && opera != '/')) ||
    (opera == EndChar && topopera != FlagChar)) 
    //当前运算符优先级低于栈顶运算符优先级
    {
    switch (topopera)
    {
    case '+':
    data = (double)NS[NS.Count-2] + (double)NS[NS.Count-1];
    break;
    case '-':
    data = (double)NS[NS.Count-2] - (double)NS[NS.Count-1];
    break;
    case '*':
    data = (double)NS[NS.Count-2] * (double)NS[NS.Count-1];
    break;
    case '/':
    data = (double)NS[NS.Count-2] / (double)NS[NS.Count-1];
    break;
    }
    NS.RemoveAt(NS.Count-1);
    NS.RemoveAt(NS.Count-1);
    NS.Add(data);
    OS.RemoveAt(OS.Count-1);
    if (OS.Count == 0)
    topopera = FlagChar;
    else
    topopera = (char)OS[OS.Count-1];
    }
    if (opera == EndChar)
    {
    result = (double)NS[NS.Count-1];
    }
    else
    {
    OS.Add(opera);
    }
    }
    expression = expression.Substring(index+1,expression.Length-index-1);
    }
    catch (Exception ec)
    {
    throw new Exception("非法的表达式。", ec);
    }
    }
    }
    return result;
    }
      

  2.   

    首先需要分词,比如+,-都是一个词.将数字也可以分出来,
    20+3*5-10/2.5分为
    "20" , "+" ,  "3" , "*" , "5" , "-" , "10" , "/" , 2.5然后进行语法分析.使用二个堆栈,一个数值,一个是操作符.操作符需要定义优先级.
    读入数字时将数字push到数字堆栈,读入符号时先将高于操作符的优先级重新计算出数值.并压入数值堆栈中.依上例
    读入20 数值堆栈为20 操作符堆栈为空
    读入+ 数值堆栈为20 操作符堆栈为+
    读入3 数值堆栈为20 3 操作符堆栈为+
    读入* 数值堆栈为20 3 操作符堆栈为+ *
    读入5 数值堆栈为20 3 5 操作符堆栈为 + *
    读入- 由于+ *的优先级高于或者等于-,所以将3*5计算出15放入堆栈中.然后计算20+15得出35放回堆栈中,数值堆栈为35 操作符堆栈为空.
    这种方式要加入括号也很简单.还有更好的方式就是下一个类似于yacc的东东.很容易实现这个功能的.
      

  3.   

    使用stack来处理。
    将表达式改写成后缀式表达式:
    (2+3)*2 --> 23+2*