/// <summary>计算四则表达式</summary> private decimal[] CalculateTwoParms() { string left, right, op; GetNext(_expression, out left, out op, out right); decimal[] result, r; //如果下一个运算符的级别不大于当前运算符,则计算当前的值 if (op == null || (GetOperatorLevel(_opt) >= GetOperatorLevel(op))) r = Calc(_opt, _leftValue, left); else { //如果下一个运算符的级别大于当前运算符 string ex = left; //则一直找到低于当前运算符级别的运算符,然后将该运算符和当前运算符中间的表达式 //提取出来,新构造一个对象,运算中间级别高的表达式的值 //然后将新对爱的结果当作右边的值于当前的左值以及运算符进行运算 while ((GetOperatorLevel(_opt) < GetOperatorLevel(op) && right != string.Empty)) { ex += op; if (GetOperatorLevel(op) == MAX_LEVEL) { int pos = GetIndex(right); ex += right.Substring(0, pos + 1); right = right.Substring(pos + 1); } GetNext(right, out left, out op, out right); ex += left; } FormulaCalculator calc = new FormulaCalculator(ex, _data); decimal[] rl = calc.Calculate(); r = Calc(_opt, _leftValue, rl[rl.Length - 1].ToString()); } //将上一步计算出来的结果作为当前的左值,然后将表达式剩下的部分作为当前的右边的表达式 //然后将下一个运算符作为当前运算符,然后递归运算 _leftValue = r[r.Length - 1].ToString(); _opt = op; _expression = right; decimal[] rr = Calculate(); result = new decimal[r.Length - 1 + rr.Length]; for (int i = 0; i < r.Length - 1; i++) result[i] = r[i]; for (int i = 0; i < rr.Length; i++) result[r.Length - 1 + i] = rr[i]; return result; }
private decimal[] Calc(string opt, string expression) { FormulaCalculator calc = new FormulaCalculator(expression, _data); decimal[] values = calc.Calculate(); decimal v = values[values.Length - 1]; decimal r = decimal.Zero; switch (_opt) { case "(": r = v; break; case "ROUND(": if (values.Length > 2) throw new Exception("Round函数需要一个或两个参数!"); if (values.Length == 1) r = decimal.Round(v, 0); else r = decimal.Round(values[0], (int)values[1]); break; case "TRUNC(": if (values.Length > 1) throw new Exception("Trunc函数只需要一个参数!"); r = decimal.Truncate(v); break; case "MAX(": if (values.Length < 2) throw new Exception("Max函数至少需要两个参数!"); r = values[0]; for (int i = 1; i < values.Length; i++) if (values[i] > r) r = values[i]; break; case "MIN(": if (values.Length < 2) throw new Exception("Min函数至少需要两个参数!"); r = values[0]; for (int i = 1; i < values.Length; i++) if (values[i] < r) r = values[i]; break; case "ABS": if (values.Length > 1) throw new Exception("Abs函数只需要一个参数!"); r = Math.Abs(v); break; case "SUM(": foreach (decimal d in values) r += d; break; case "AVERAGE(": foreach (decimal d in values) r += d; r /= values.Length; break; case "IF(": if (values.Length != 3) throw new Exception("IF函数需要三个参数!"); if (GetBoolean(values[0])) r = values[1]; else r = values[2]; break; case "NOT(": if (values.Length != 1) throw new Exception("NOT函数需要一个参数!"); if (GetBoolean(values[0])) r = 0; else r = 1; break; case "OR(": if (values.Length < 1) throw new Exception("OR函数至少需要两个参数!"); foreach (decimal d in values) if (GetBoolean(d)) return new decimal[1] { 1 }; break; case "AND(": if (values.Length < 1) throw new Exception("AND函数至少需要两个参数!"); foreach (decimal d in values) if (!GetBoolean(d)) return new decimal[1] { decimal.Zero }; r = 1; break; case "SQRT(": if (values.Length != 1) throw new Exception("SQRT函数需要一个参数!"); r = (decimal)Math.Sqrt((double)v); break; case "SIN(": if (values.Length != 1) throw new Exception("Sin函数需要一个参数!"); r = (decimal)Math.Sin((double)v); break; case "COS(": if (values.Length != 1) throw new Exception("Cos函数需要一个参数!"); r = (decimal)Math.Cos((double)v); break; case "TAN(": if (values.Length != 1) throw new Exception("Tan函数需要一个参数!"); r = (decimal)Math.Tan((double)v); break; case "EXP(": if (values.Length != 1) throw new Exception("Exp函数需要一个参数!"); r = (decimal)Math.Exp((double)v); break; case "LOG(": if (values.Length > 2) throw new Exception("Log函数需要一个或两个参数!"); if (values.Length == 1) r = (decimal)Math.Log((double)v); else r = (decimal)Math.Log((double)values[0], (double)values[1]); break; case "LOG10(": if (values.Length != 1) throw new Exception("Log10函数需要一个参数!"); r = (decimal)Math.Log10((double)v); break; } return new decimal[1] { r }; }
public static decimal[] CalculateExpression(string expression, NameValueCollection dataProvider) { FormulaCalculator calc = new FormulaCalculator(expression, dataProvider); decimal[] r = calc.Calculate(); return r; }