
Parsing of math equations from text expressions is the interesting thing. This task is close to LL parsing but can be solved in different ways. This approach tends to be the simplest one.
From time to time some of your customers might ask you to extend current functions of your system with ability to specify some simple math formulas. This is tricky challenge if you have no relevant experience. Well, omitting all that theoretical things and go further. The code below could help you calculate simple math formulas with braces. Take a look at the screen-shot to get what I mean:
Below you can find that evaluator which can be simply integrated into your code. Have a look at the usage sample below:
1 2 3 4 |
StrExpr.StrExpr se = new StrExpr.StrExpr(); txtResult.Text = se.Parse(txtExpression.Text); |
And the evaluator source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
public class StrExpr { private readonly Hashtable _opTagList = new Hashtable(); private ArrayList _opList; private ArrayList _figuresList; public StrExpr() { _opTagList.Add('+', 0); _opTagList.Add('-', 0); _opTagList.Add('*', 1); _opTagList.Add('/', 1); _opTagList.Add('(', 10); _opTagList.Add(')', -10); } public string Parse(string text) { _figuresList = new ArrayList(); _opList = new ArrayList(); return this.Evaluate(text.Trim()); } private string Evaluate(string text) { if (text != null) { #region Parsing StringBuilder expr = new StringBuilder(text); char[] ops = new char[] { '+', '-', '*', '/', '(', ')' }; int opIndex = expr.ToString().IndexOfAny(ops); int priority = 0; while (opIndex != -1) { if (opIndex > 0) { _figuresList.Add(double.Parse(expr.ToString().Substring(0, opIndex))); expr.Remove(0, opIndex); opIndex = expr.ToString().IndexOfAny(ops); if (opIndex == -1) break; } char op = expr[0]; priority += (int)_opTagList[op]; if (!((op == '(') || (op == ')'))) { _opList.Add(new DictionaryEntry(op, priority)); } expr.Remove(0, 1); opIndex = expr.ToString().IndexOfAny(ops); if ((opIndex == -1) && (expr.Length > 0)) opIndex = expr.Length; } #endregion #region Calculating while (_opList.Count > 0) { #region Find max priority DictionaryEntry maxPriorityOp = (DictionaryEntry)_opList[0]; foreach (DictionaryEntry entry in _opList) { if ((int)entry.Value > (int)maxPriorityOp.Value) { maxPriorityOp = entry; } } #endregion int index = _opList.IndexOf(maxPriorityOp); double op1 = (double)_figuresList[index]; double op2 = (double)_figuresList[index + 1]; object d = null; switch ((char)maxPriorityOp.Key) { case '+': d = op1 + op2; break; case '-': d = op1 - op2; break; case '*': d = op1 * op2; break; case '/': d = op1 / op2; break; } _opList.Remove(maxPriorityOp); _figuresList.RemoveAt(index + 1); _figuresList.RemoveAt(index); if (d != null) _figuresList.Insert(index, (double)d); } return _figuresList[0].ToString(); #endregion } return string.Empty; } } |