【类】C#计算器类(SamWang)

  1 /******************************************************************
  2  * 创 建 人:  SamWang
  3  * 创建时间:  2011-11-29
  4  * 描    述:
  5  *             计算器类:能直接对表达式进行计算,支持变量
  6  * 原    理:  将表达式按字符压入堆栈中,然后按照各操作符的级别进行处理
  7  * 版    本:  V1.0      
  8  * 环    境:  VS2005
  9 ******************************************************************/
 10 using System;
 11 using System.Collections.Generic;
 12 using System.Text;
 13 using System.Windows.Forms;
 14 using System.Collections;
 15 
 16 namespace LingDang.CRM.UI.Client
 17 {
 18     public class Calculator
 19     {
 20         private string _expression;
 21         private Stack s;
 22         private string[] values;
 23 
 24         /// <summary>
 25         /// 构造函数
 26         /// </summary>
 27         /// <param name="expression">表达式</param>
 28         /// <param name="varValues">变量值数组</param>
 29         public Calculator(string expression, string[] varValues)
 30         {
 31             this._expression = expression.ToLower();
 32             s = new Stack();
 33             values = varValues;
 34         }
 35 
 36         /// <summary>
 37         /// 构造函数
 38         /// </summary>
 39         /// <param name="expression">表达式</param>
 40         public Calculator(string expression)
 41         {
 42             this._expression = expression;
 43             s = new Stack();
 44         }
 45 
 46         /// <summary>
 47         /// 总运行
 48         /// </summary>
 49         /// <returns></returns>
 50         public double Run()
 51         {
 52             string expression = PostFix();
 53             string[] aryString = expression.Split('|');
 54 
 55             foreach (string str in aryString)
 56             {
 57                 if (IsNumber(str) || IsVarible(str[0]))
 58                 {
 59                     double d;
 60                     if (IsVarible(str[0]))
 61                     {
 62                         d = Convert.ToDouble(GetValue(str[0]));
 63                     }
 64                     else
 65                     {
 66                         d = Convert.ToDouble(str.ToString());
 67                     }
 68                     AddOperands(d);
 69                 }
 70                 else
 71                 {
 72                     DoOperator(str);
 73                 }
 74 
 75             }
 76             return (double)s.Pop();
 77         }
 78 
 79 
 80         private bool IsNumber(string str)
 81         {
 82             if (str.Length > 1)
 83             {
 84                 return true;
 85             }
 86             else
 87             {
 88                 return Char.IsDigit(str[0]);
 89             }
 90         }
 91 
 92         /// <summary>
 93         /// 判断是否为变量,变量范围为a-z
 94         /// </summary>
 95         /// <param name="c"></param>
 96         /// <returns></returns>
 97         private bool IsVarible(char c)
 98         {
 99             if (c >= 'a' && c <= 'z')
100             {
101                 return true;
102             }
103             else
104             {
105                 return false;
106             }
107         }
108 
109 
110         private void AddOperands(double val)
111         {
112             s.Push(val);
113         }
114 
115         /// <summary>
116         /// 得到公式左右运算数
117         /// </summary>
118         /// <param name="left"></param>
119         /// <param name="right"></param>
120         /// <returns></returns>
121         private bool GetTwoOperands(out double left, out double right)
122         {
123             try
124             {
125                 right = (double)s.Pop();
126                 left = (double)s.Pop();
127             }
128             catch (InvalidOperationException)
129             {
130                 right = 0;
131                 left = 0;
132                 return false;
133             }
134             return true;
135         }
136 
137         /// <summary>
138         /// 计算操作
139         /// </summary>
140         /// <param name="op">运算符</param>
141         private void DoOperator(string op)
142         {
143             double left, right;
144             bool result = GetTwoOperands(out left, out right);
145             if (result)
146             {
147                 switch (op)
148                 {
149                     case "+": s.Push(left + right); break;
150                     case "-": s.Push(left - right); break;
151                     case "*": s.Push(left * right); break;
152                     case "/":
153                         if (right == 0.0)
154                         {
155                             s.Clear();
156                             //Divide by 0!
157                             throw new Exception("除数不能为零");
158                         }
159                         else
160                             s.Push(left / right);
161                         break;
162                     case "^":
163                         s.Push(Math.Pow(left, right));
164                         break;
165                 }
166             }
167             else
168             {
169                 s.Clear();
170             }
171         }
172 
173         /// <summary>
174         /// 解析为后缀表达式
175         /// </summary>
176         /// <returns></returns>
177         public string PostFix()
178         {
179             string str = this._expression + "#";
180             char tempc;
181             char[] chars = str.ToCharArray();
182             Stack ts = new Stack();
183             ts.Push('#');
184             string str1 = "";
185             string tmpStr = "";
186             bool isNum = false;
187             foreach (char c in chars)
188             {
189                 if (Char.IsDigit(c) || IsVarible(c) || c == '.')
190                 {
191                     tmpStr += c.ToString();
192                     isNum = true;
193                 }
194                 else
195                 {
196                     if (isNum)
197                     {
198                         str1 += tmpStr + "|";
199                         tmpStr = "";
200                     }
201                     isNum = false;
202                     if (c == ')')
203                     {
204                         for (tempc = Convert.ToChar(ts.Pop()); tempc != '('; tempc = Convert.ToChar(ts.Pop()))
205                             str1 += tempc.ToString() + "|";
206                     }
207                     else
208                     {
209                         for (tempc = Convert.ToChar(ts.Pop()); Isp(tempc) > Icp(c); tempc = Convert.ToChar(ts.Pop()))
210                             str1 += tempc.ToString() + "|";
211                         ts.Push(tempc);
212                         ts.Push(c);
213                     }
214                 }
215             }
216             return str1.Substring(0, str1.Length - 1);
217         }
218 
219         /// <summary>
220         /// 根据变量名得到对应的值
221         /// </summary>
222         /// <param name="c">变量名:A-Z</param>
223         /// <returns></returns>
224         private string GetValue(char c)
225         {
226             string result = "0";
227             //变量对应的数组位置
228             int index = Convert.ToInt32(c) - Convert.ToInt32('a');
229             if (index < values.Length)
230             {
231                 result = values[index].ToString();
232             }
233             return result;
234         }
235 
236         private int Isp(char c)
237         {
238             int k;
239             switch (c)
240             {
241                 case '#': k = 0; break;
242                 case '(': k = 1; break;
243                 case '^': k = 7; break;
244                 case '*':
245                 case '/':
246                 case '%': k = 5; break;
247                 case '+':
248                 case '-': k = 3; break;
249                 case ')': k = 8; break;
250                 default:
251                     //Unknown operator!
252                     throw new Exception("无效操作符:"+c.ToString());
253             }
254             return k;
255         }
256 
257         private int Icp(char c)
258         {
259             int k;
260             switch (c)
261             {
262                 case '#': k = 0; break;
263                 case '(': k = 8; break;
264                 case '^': k = 6; break;
265                 case '*':
266                 case '/':
267                 case '%': k = 4; break;
268                 case '+':
269                 case '-': k = 2; break;
270                 case ')': k = 1; break;
271                 default:
272                     //Unknown operator!
273                     throw new Exception("无效操作符:" + c.ToString());
274             }
275             return k;
276         }
277     }
278 }

 

作者:SamWang
出处:http://wangshenhe.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。

posted on 2012-05-09 17:20  SamWang  阅读(1553)  评论(0编辑  收藏  举报