C#实现eval 进行四则运算(有码)
在JavaScript中实现四则运算很简单,只需要调用eval函数就行了,但是不知道什么原因万能的.NET却没有封装这个函数~
在这里为大家封装了一个C#版本的eval函数,具体的设计参考了《大话数据结构》
1. 中缀表达式
中缀表达式即我们平时使用的四则运算表达式,如:9+(3-1)*3+10/2,但是程序却很难识别这样的表达式,所以需要把它转化成后缀表达式
2. 后缀表达式
因为所有的运算符都在数字后面,所以称其为后缀表达式,如:9 3 1 – 3 * + 10 2 / +,那么程序如何识别后缀表达式呢,这里就用到了栈(Stack),主要分以下步骤:
1) 将字符从前往后进行入栈操作
2)如果字符为数字则直接入栈,如:上例中的9、3、1都直接入栈
3)如果为运算符则获取栈顶的两个数字,即执行两次pop操作,如:在执行到上例中的“-”时,将3、1出栈,然后运行3-1
4)将上一步运算的结果入栈,即将3-1=2入栈
5) 根据以上原则,运行的顺序如下:3-1=2,2*3=6,9+6=15,10/2=5,15+5=20,20就是我们想要的结果
3. 中缀表达式转后缀表达式
这里还是得用到栈(Stack),我们还是用 9+(3-1)*3+10/2 来做例子,原则如下:
1)将字符从前往后进行入栈操作
2)当字符为数字时直接输出,如:上例中9直接输出
3)当字符为运算符时,如果是空栈则直接入栈,如下图步骤1
4)如果是“(”则直接入栈,如步骤2
5) 如果是“)”则循环取出栈内元素,直到“(”出栈,再将“()”内的运算符输出,如步骤4
6)如果是“*”或“/”则直接入栈,如步骤5
7)如果是“+”或“-”,且栈顶的运算符为“*”或“/”,则取出所有栈内元素输出,然后将本次操作符入栈,如步骤6
8)表达式遍历完成后,循环取出栈内元素进行输出,我们最后得到的结果就是 9 3 1 – 3 * + 10 2 / +
4.实现源码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Calculator 2 { 3 public Calculator() 4 { 5 _OptStack = new Stack<char>(); 6 _SuffixStack = new Stack<float>(); 7 } 8 9 private Stack<char> _OptStack; 10 private Stack<float> _SuffixStack; 11 12 public float Calculate(string expression) 13 { 14 string lastNum = string.Empty; 15 for (int i = 0; i < expression.Length; i++) 16 { 17 if (char.IsNumber(expression[i]) || expression[i].Equals('.')) 18 { 19 lastNum += expression[i]; 20 } 21 else 22 { 23 if (lastNum != string.Empty) 24 { 25 Merger(float.Parse(lastNum)); 26 lastNum = string.Empty; 27 } 28 AddOpt(expression[i]); 29 } 30 } 31 if (lastNum != string.Empty) 32 { 33 Merger(float.Parse(lastNum)); 34 } 35 while (_OptStack.Count > 0) 36 { 37 Merger(_OptStack.Pop()); 38 } 39 40 return _SuffixStack.Pop(); 41 } 42 43 private void AddOpt(char opt) 44 { 45 if (_OptStack.Count == 0) 46 { 47 _OptStack.Push(opt); 48 return; 49 } 50 if (opt.Equals(')')) 51 { 52 while (!_OptStack.Peek().Equals('(')) 53 { 54 Merger(_OptStack.Pop()); 55 } 56 _OptStack.Pop(); 57 return; 58 } 59 char tempOpt = _OptStack.Peek(); 60 if ((opt.Equals('-') || opt.Equals('+')) && 61 (tempOpt.Equals('*') || tempOpt.Equals('/'))) 62 { 63 while (_OptStack.Count > 0) 64 { 65 Merger(_OptStack.Pop()); 66 } 67 } 68 69 _OptStack.Push(opt); 70 } 71 72 private void Merger(float exp) 73 { 74 _SuffixStack.Push(exp); 75 } 76 77 private void Merger(char exp) 78 { 79 float num1 = _SuffixStack.Pop(); 80 float num2 = _SuffixStack.Pop(); 81 float result = 0; 82 switch (exp) 83 { 84 case '+': 85 result = num2 + num1; 86 break; 87 case '-': 88 result = num2 - num1; 89 break; 90 case '*': 91 result = num2 * num1; 92 break; 93 case '/': 94 result = num2 / num1; 95 break; 96 } 97 _SuffixStack.Push(result); 98 } 99 }
5. 下载