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 ///25 /// 构造函数 26 /// 27 /// 表达式 28 /// 变量值数组 29 public Calculator(string expression, string[] varValues) 30 { 31 this._expression = expression.ToLower(); 32 s = new Stack(); 33 values = varValues; 34 } 35 36 ///37 /// 构造函数 38 /// 39 /// 表达式 40 public Calculator(string expression) 41 { 42 this._expression = expression; 43 s = new Stack(); 44 } 45 46 ///47 /// 总运行 48 /// 49 ///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 /// 93 /// 判断是否为变量,变量范围为a-z 94 /// 95 /// 96 ///97 private bool IsVarible(char c) 98 { 99 if (c >= 'a' && c <= 'z')100 {101 return true;102 }103 else104 {105 return false;106 }107 }108 109 110 private void AddOperands(double val)111 {112 s.Push(val);113 }114 115 /// 116 /// 得到公式左右运算数117 /// 118 /// 119 /// 120 ///121 private bool GetTwoOperands(out double left, out double right)122 {123 try124 {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 /// 138 /// 计算操作139 /// 140 /// 运算符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 else160 s.Push(left / right);161 break;162 case "^":163 s.Push(Math.Pow(left, right));164 break;165 }166 }167 else168 {169 s.Clear();170 }171 }172 173 ///174 /// 解析为后缀表达式175 /// 176 ///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 else195 {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 else208 {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 /// 220 /// 根据变量名得到对应的值221 /// 222 /// 变量名:A-Z223 ///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 }
作者:
出处: 本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。