【类】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/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。