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.实现源码如下:

  

 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     }
View Code

 

5. 下载

 Demo.rar

 

 

posted @ 2013-06-24 19:11  Sanco  阅读(4162)  评论(6编辑  收藏  举报