예제 #1
0
        public void SubstituteOperationsWithResult(ref string calculationString, string symbol)
        {
            do
            {
                if (!calculationString.Contains(symbol))
                {
                    break;
                }

                // Break if Negative Result, with no other calculations eg. -50
                if (symbol == OperatorSymbol.Subtract && calculationString.Substring(0, 1) == symbol && !calculationString.Substring(1).Contains(symbol))
                {
                    break;
                }

                // Break if Double Negative Result, with no other calculations eg. --50
                if (symbol == OperatorSymbol.Subtract && calculationString.Substring(0, 2) == (symbol + symbol) && !calculationString.Substring(2).Contains(symbol))
                {
                    calculationString = calculationString.Replace((symbol + symbol), "");

                    break;
                }

                string operationString = _operationIdentifier.GetNextOperationMatch(calculationString, symbol);

                IOperator Operation = _operationFactory.Create(operationString);

                decimal Result = Operation.GetResult();

                calculationString = calculationString.Replace(operationString, Result.ToString());
            }while (calculationString.Contains(symbol));
        }
예제 #2
0
        /// <summary>
        /// A method which calculates a given expression.</summary>
        /// <param name="separated"> A infix notation expression InputElement list</param>
        /// <returns> A calculation result status </returns>
        private CalculateResult Calculate(IEnumerable <InputElement> separated)
        {
            Status = WorkingStatus.ERROR;

            if (separated.Count() < 1)
            {
                Result = 0;
                Status = WorkingStatus.WORKING;
                return(new CalculateSuccess());
            }

            if (separated.Last() is Point)
            {
                return(new CalculateFailed());
            }

            IList <InputElement> temp = new List <InputElement>(separated);
            {
                int res = 0;
                foreach (var item in temp)
                {
                    if (item.CompareTo("(") == 0)
                    {
                        res += 1;
                    }
                    else if (item.CompareTo(")") == 0)
                    {
                        res -= 1;
                    }
                }

                for (int i = 0; i < res; i++)
                {
                    temp.Add(new CloseBracket());
                }
            }

            Queue <InputElement> postfix = new Queue <InputElement>();

            if (ChangeToPostfix(temp, out postfix) == false)
            {
                return(new CantCalculateInvalidFormat());
            }

            Stack <string> operand = new Stack <string>();

            try
            {
                while (postfix.Count > 0)
                {
                    InputElement token = postfix.Dequeue();

                    if (token is Literal)
                    {
                        operand.Push(token.GetElement);
                    }
                    else
                    {
                        IOperator op = OperatorsPriority[token];
                        string    op1;
                        string    op2;
                        double    _op1 = 0;
                        double    _op2 = 0;

                        if (op is IBinaryOperator)
                        {
                            op2 = operand.Pop();
                            op1 = operand.Pop();

                            if (GetDoubleValue(op2, out _op2) == false ||
                                GetDoubleValue(op1, out _op1) == false)
                            {
                                return(new CantCalculateInvalidFormat());
                            }

                            if ((op is Models.Point) == false)
                            {
                                LastOperand  = new Literal(op2);
                                LastOperator = op;
                            }
                        }
                        else if (op is IUnaryOperator)
                        {
                            op1 = operand.Pop();

                            if (GetDoubleValue(op1, out _op1) == false)
                            {
                                return(new CantCalculateInvalidFormat());
                            }
                        }

                        double result = 0;
                        op.GetResult(_op1, _op2, out result);
                        if (Double.IsInfinity(result) ||
                            Double.IsNaN(result))
                        {
                            return(new CantCalculateTooBigNumber());
                        }

                        // Exceptional Case : %
                        if (op.ToString().CompareTo("%") == 0)
                        {
                            if (operand.Count > 0)
                            {
                                if (postfix.Count == 0 ||
                                    (postfix.Count > 0 &&
                                     postfix.Peek().CompareTo("/") != 0 &&
                                     postfix.Peek().CompareTo("*") != 0))
                                {
                                    double prevLiteral = Double.Parse(operand.Peek());
                                    result = prevLiteral * result;
                                }
                            }
                        }

                        operand.Push(result.ToString());
                    }
                }
            }
            catch (Exception e)
            {
                if (e is InvalidOperationException ||
                    e is InvalidNumberException)
                {
                    return(new CantCalculateInvalidFormat());
                }
                else if (e is DivideByZeroException)
                {
                    return(new CantDivideByZero());
                }
                else if (e is TooBigNumberException)
                {
                    return(new CantCalculateTooBigNumber());
                }

                return(new CalculateFailed());
            }

            double ret;

            if (operand.Count == 0 ||
                Double.TryParse(operand.Peek(), out ret) == false)
            {
                return(new CalculateFailed());
            }

            Result = ret;
            Status = WorkingStatus.WORKING;
            return(new CalculateSuccess());
        }
        /// <summary>
        /// The method calculates result for given expression.
        /// </summary>
        /// <param name="separated"> InputElement list in infix notation</param>
        /// <returns> Calculation result status </returns>
        private CalculationResult Calculate(IEnumerable <InputElement> separated)
        {
            Status = WorkingStatus.ERROR;

            if (!separated.Any())
            {
                Result = 0;
                Status = WorkingStatus.WORKING;
                return(new CalculationSuccessful());
            }

            if (separated.Last() is Point)
            {
                return(new CalculationFailed());
            }

            IList <InputElement> temp = new List <InputElement>(separated);
            // This section adds missing closing brackets
            {
                int depth = 0;
                foreach (var item in temp)
                {
                    if (item.CompareTo("(") == 0)
                    {
                        depth += 1;
                    }
                    else if (item.CompareTo(")") == 0)
                    {
                        depth -= 1;
                    }
                }

                for (int i = 0; i < depth; i++)
                {
                    temp.Add(new CloseBracket());
                }
            }


            Queue <InputElement> postfix;

            if (!ChangeToPostfix(temp, out postfix))
            {
                return(new CantCalculateInvalidFormat());
            }

            Stack <string> operand = new Stack <string>();

            try
            {
                foreach (var token in postfix)
                {
                    if (token is Literal)
                    {
                        operand.Push(token.GetElement);
                    }
                    else
                    {
                        IOperator op = OperatorDescriptions[token];
                        string    op1;
                        string    op2;
                        double    _op1 = 0;
                        double    _op2 = 0;

                        // This section retrives arguments needed by operator
                        if (op is IBinaryOperator)
                        {
                            op2 = operand.Pop();
                            op1 = operand.Pop();

                            if (!GetDoubleValue(op2, out _op2) || !GetDoubleValue(op1, out _op1))
                            {
                                return(new CantCalculateInvalidFormat());
                            }

                            if ((op is Models.Point) == false)
                            {
                                LastOperand  = new Literal(op2);
                                LastOperator = op;
                            }
                        }
                        else if (op is IUnaryOperator)
                        {
                            op1 = operand.Pop();

                            if (!GetDoubleValue(op1, out _op1))
                            {
                                return(new CantCalculateInvalidFormat());
                            }
                        }

                        op.GetResult(_op1, _op2, out double result);

                        if (Double.IsInfinity(result) || Double.IsNaN(result))
                        {
                            return(new CantCalculateTooBigNumber());
                        }

                        operand.Push(result.ToString());
                    }
                }
            }
            catch (DivideByZeroException)
            {
                return(new CantDivideByZero());
            }
            catch (InvalidOperationException)
            {
                return(new CantCalculateInvalidFormat());
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
                return(new CalculationFailed());
            }

            double ret;

            if (operand.Count == 0 || Double.TryParse(operand.Peek(), out ret) == false)
            {
                return(new CalculationFailed());
            }

            Result = ret;
            Status = WorkingStatus.WORKING;
            return(new CalculationSuccessful());
        }