static void Main(string[] args) { while (true) { Console.WriteLine("Please enter any mathematical expression:"); var strExpression = Regex.Replace(Console.ReadLine(), " ", ""); if (strExpression.ToLower() == "exit") { break; } //strExpression = "12 + sqrt((1+3)*abs(-5+1-(2+3-2-3)))*max(-abs(-1),min(-5,-3))-min(12,128)"; //strExpression = "abs(min(a,-100))*sqrt(a*b)+c-d%e"; //strExpression = "(7*9-(-abs(9* 5)/ (9 / 6)))"; //strExpression = "pow(5,2)"; strExpression = "abs(23-4*(8+Pow(6-3,(1+1))*4-10))"; var handler = new ExpressionHandler(strExpression); var variableValues = new List <String>(); foreach (var variableName in handler.VariableNames) { Console.WriteLine(String.Format("Please enter value for [{0}]:", variableName)); var variableValue = Regex.Replace(Console.ReadLine(), " ", "").TrimStart('+'); while (!Helper.IsNumericValue(variableValue)) { Console.WriteLine("Please enter a VALID value!!!"); variableValue = Regex.Replace(Console.ReadLine(), " ", "").TrimStart('+'); } variableValues.Add(variableValue); } var value = handler.Calculate(variableValues); Console.WriteLine(String.Format("Result:\r\n{0}\r\n", value)); } }
public static IComputeUnit Parse(String replacedExpression) { var normalizedExpression = Normalize(replacedExpression); if (Helper.IsNumericValue(normalizedExpression)) { return(new NumericUnit(normalizedExpression)); } String strExpression; SimpleFunctions simplefunction; if (TrySimpleParse(normalizedExpression, out strExpression, out simplefunction)) { return(new SimpleUnit(strExpression, simplefunction)); } ComplexFunctions complexFunction; if (TryComplexParse(normalizedExpression, out strExpression, out complexFunction)) { return(new ComplexUnit(strExpression, complexFunction)); } return(null); }
public override Double Compute() { try { return(Helper.IsNumericValue(this.Expression) ? Double.Parse(this.Expression) : Double.NaN); } catch { return(Double.NaN); } }
public static String Normalize(String strExpression) { if (String.IsNullOrWhiteSpace(strExpression)) { return("0"); } var expression = strExpression.TrimStart('+'); // remove prefix '+'; while (Regex.IsMatch(expression, @"^[([{]") && Regex.IsMatch(expression, @"[)\]}]$") && Helper.GetSubExpression(expression) == expression) { expression = expression.Substring(1, expression.Length - 2).TrimStart('+'); // remove unnecessary bounded "()"; } if (String.IsNullOrWhiteSpace(expression)) { return("0"); } if (Helper.IsNumericValue(expression)) { return(expression); } if (expression[0] != '+' && expression[0] != '-') { return(expression); } // ZEHONG: maybe here is redundant, add a prefix "0" is no problem I think////////////////////////// var matchs = Regex.Matches(expression, @"[\+\-*/%\,]").OfType <Match>().ToList(); // '+', '-', '*', '/', '%' , ',' if (matchs.Count >= 2) { var temp = expression.Substring(0, matchs[1].Index); if (Helper.IsNumericValue(temp)) // if expression starts with '+' or '-', add "()" to it. { expression = expression.Insert(matchs[1].Index, ")"); expression = expression.Insert(0, "("); return(expression); } } /////////////////////////////////////////////////////////////////////////////////////////////// return("0" + expression); }
public override Double Compute() { if (String.IsNullOrWhiteSpace(this.Expression)) { return(Double.NaN); } if (Helper.IsNumericValue(this.Expression)) { return(this.ApplyFunction(Double.Parse(this.Expression))); } var _operatorList = new List <String>(); var _unitList = new List <IComputeUnit>(); try { // prepare int i = 0; while (i < Expression.Length) { var strExpression = Expression.Substring(i); var nextMatch = Regex.Match(strExpression, @"[\+\-*/%([{]"); if (!nextMatch.Success) // must be numeric number { _unitList.Add(new NumericUnit(strExpression)); break; } if (nextMatch.Index == 0) { if (Regex.IsMatch(nextMatch.Value, @"[([{]")) { var subExpression = Helper.GetSubExpression(strExpression); var unit = ExpressionHandler.Parse(subExpression); if (unit == null) { return(Double.NaN); } _unitList.Add(unit); i += subExpression.Length; } else if (Regex.IsMatch(nextMatch.Value, @"[\+\-*/%]")) { Debug.Assert(nextMatch.Index == 0 && nextMatch.Length == 1); _operatorList.Add(strExpression[0].ToString()); i++; } } else { if (Regex.IsMatch(strExpression, @"^[0-9]")) // start with number, it must be a numeric unit { _unitList.Add(new NumericUnit(strExpression.Substring(0, nextMatch.Index))); i += nextMatch.Index; } else // must be a complex unit { var subExpression = Helper.GetSubExpression(strExpression); var unit = ExpressionHandler.Parse(subExpression); if (unit == null) { return(Double.NaN); } _unitList.Add(unit); i += subExpression.Length; } } } // calculate Debug.Assert(_operatorList.Count == _unitList.Count - 1); var operators = new List <String>(); var values = new List <Double>(); Double value = Double.NaN; for (i = 0; i < _operatorList.Count; i++) { if (Double.IsNaN(value)) { value = _unitList[i].Compute(); } if (Double.IsNaN(value)) { return(Double.NaN); } if (_operatorList[i] == "*" || _operatorList[i] == "/" || _operatorList[i] == "%") { if (_operatorList[i] == "*") { value *= _unitList[i + 1].Compute(); } else { var temp = _unitList[i + 1].Compute(); if (temp == 0) { return(Double.NaN); } if (_operatorList[i] == "/") { value /= temp; } else { value %= temp; } } continue; } if (Double.IsNaN(value)) { return(Double.NaN); } if (operators.Any() && operators.Last() == "-") { value *= -1; } values.Add(value); operators.Add(_operatorList[i]); value = Double.NaN; } if (Double.IsNaN(value) && (!_operatorList.Any() || _operatorList.Last() == "+" || _operatorList.Last() == "-")) { value = _unitList.Last().Compute(); } if (!Double.IsNaN(value)) { if (operators.Any() && operators.Last() == "-") { value *= -1; } values.Add(value); } // apply function return(this.ApplyFunction(values.Sum())); } catch { return(Double.NaN); } finally { _operatorList.Clear(); _unitList.Clear(); } }
private List <String> GetVariables() { try { if (String.IsNullOrWhiteSpace(this.Expression)) { return(new List <String>()); } //var chars = System.IO.Path.GetInvalidFileNameChars(); //if (object.ReferenceEquals(chars, this.Expression)) // return new List<String>(); var functionNames = Enum.GetNames(typeof(SimpleFunctions)).Select(p => p.ToUpper()).ToList(); var complexFunctionNames = Enum.GetNames(typeof(ComplexFunctions)).Select(p => p.ToUpper()).ToList(); var variableNames = this.Expression.Split(SupportOperators, StringSplitOptions.RemoveEmptyEntries); return(variableNames.Where(p => !functionNames.Contains(p.ToUpper()) && !complexFunctionNames.Contains(p.ToUpper()) && !Helper.IsNumericValue(p)).Distinct().ToList()); } catch { return(new List <String>()); } }
public Double Calculate(List <String> variableValues) { try { if (variableValues == null || this.VariableNames.Count != variableValues.Count || variableValues.Any(p => !Helper.IsNumericValue(p))) { return(Double.NaN); } var replacedExpression = this.Expression; var newValues = variableValues.Select(p => p.TrimStart('+')).Select(p => p[0] == '-' ? String.Format("({0})", p) : p).ToList(); for (int i = 0; i < this.VariableNames.Count; i++) { replacedExpression = Regex.Replace(replacedExpression, String.Format(@"\b{0}\b", this.VariableNames[i]), newValues[i]); } var expressionUnit = Parse(replacedExpression); if (expressionUnit != null) { return(expressionUnit.Compute()); } return(Double.NaN); } catch { return(Double.NaN); } }