Example #1
0
        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);
        }
Example #3
0
 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);
        }
Example #5
0
        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);
            }
        }