using System; using System.Collections; using System.Text; using System.Text.RegularExpressions; class Program { static void Main() { foreach(string s in new string[] { "1 + 23", // 24 "50 + 2 * 5", // 60 "( 5 + 2 ) * 3", // 21 "3 * ( 5 + 2 )", // 21 "-3 + 4", // 1 "3 + -4", // -1 "-3 + -4", // -7 "-3 - -4", // 1 "-3 * -4", // 12 "-5 + 2 * 5", // 5 "5 + 2 * -5", // -5 "((5 + 1) * 8 - 4) / 2", // 22 "-( 5 + 2 ) * 3", // -21 "3 * -( 5 + 2 )", // -21 "10 % 3 ", // 1 "10 * 0.5", // 5 "+10 * - 0 . 025", // -0.25 }) { Console.WriteLine("Eval: {0} = {1}", s, Eval(s)); } } // 計算式を評価 public static decimal Eval(string str) { CharEnumerator e = Split(str); return e.MoveNext() ? EvalAddition(e) : 0; } // 文字分割、ゴミ排除 static CharEnumerator Split(string str) { StringBuilder sb = new StringBuilder(); foreach(Match m in new Regex(@"[\(\)\+\-\*\/\%\.0-9]").Matches(str)) sb.Append(m.Value); return sb.ToString().GetEnumerator(); } // 加法式を評価 static decimal EvalAddition(CharEnumerator factor) { decimal value = EvalMultiplication(factor); while(true) { char op = new char(); try { op = factor.Current; } catch(InvalidOperationException) { break; } if(!(op == '+' || op == '-')) break; if(!factor.MoveNext()) break; // 式が途中半端? decimal val = EvalMultiplication(factor); switch(op) { case '+': value += val; break; case '-': value -= val; break; } } return value; } // 乗法式を評価 static decimal EvalMultiplication(CharEnumerator factor) { decimal value = EvalExpression(factor); while(true) { char op = new char(); try { op = factor.Current; } catch(InvalidOperationException) { break; } if(!(op == '*' || op == '/' || op == '%')) break; if(!factor.MoveNext()) break; // 式が途中半端? decimal val = EvalExpression(factor); switch(op) { case '*': value *= val; break; case '/': value /= val; break; case '%': value %= val; break; } } return value; } // 単項式の評価(処理的に基本式含む) static decimal EvalExpression(CharEnumerator factor) { decimal value = 1; if(char.IsDigit(factor.Current)) { StringBuilder sb = new StringBuilder(); sb.Append(factor.Current); while(factor.MoveNext()) { if(char.IsDigit(factor.Current) || factor.Current == '.') sb.Append(factor.Current); else break; } if(!decimal.TryParse(sb.ToString(), out value)) value = 1; } else if(factor.Current == '+') { value = factor.MoveNext() ? EvalExpression(factor) : 1; } else if(factor.Current == '-') { value = factor.MoveNext() ? EvalExpression(factor) * -1 : 1; } else if(factor.Current == '(') { value = factor.MoveNext() ? EvalAddition(factor) : 1; if(factor.Current == ')') { factor.MoveNext(); } else { } // )以外はこないはず… } return value; } }