Beispiel #1
0
 /// <summary>
 /// Mathematical calculator constructor with dependency injection
 /// </summary>
 /// <param name="parser">Parser of mathematical expression string</param>
 /// <param name="notationConverter">Converter for different mathematical notation</param>
 /// <param name="mathProcessor">Processor for performing mathematical operations</param>
 /// <param name="mathOperationsContainer">Mathematical operations</param>
 public MathCalculator(IParser parser, INotationConverter notationConverter, IMathProcessor mathProcessor, IMathOperationsContainer mathOperationsContainer)
 {
     _parser                  = parser;
     _notationConverter       = notationConverter;
     _mathProcessor           = mathProcessor;
     _mathOperationsContainer = mathOperationsContainer;
 }
Beispiel #2
0
        /// <summary>
        /// Parse string to terms of mathematical expression
        /// </summary>
        /// <param name="expression">Input expression</param>
        /// <param name="mathOperationsContainer">Avaliable math operations</param>
        /// <returns>Parsed mathematical expression</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="NullReferenceException"></exception>
        public IEnumerable <ExpressionUnit> Parse(string expression, IMathOperationsContainer mathOperationsContainer)
        {
            var result = new List <ExpressionUnit>();

            var numberBuilder = new StringBuilder();

            for (var i = 0; i < expression.Length; i++)
            {
                OperationType operationType = OperationType.Unary;

                var firstOperandExists           = numberBuilder.Length != 0;
                var firstOperandInBracketsExists = result.Count() != 0 && result.Last().Type == ExpressionUnitType.RightBracket;
                if (firstOperandExists || firstOperandInBracketsExists)
                {
                    operationType = OperationType.Binary;
                }

                if (TryParseExpressionUnit(expression[i].ToString(), operationType, mathOperationsContainer, out ExpressionUnit mathOperation))
                {
                    ParseNumber(result, numberBuilder);

                    result.Add(mathOperation);

                    continue;
                }

                numberBuilder.Append(expression[i]);
            }

            ParseNumber(result, numberBuilder);

            return(result);
        }
Beispiel #3
0
        public MathCalculatorUnitTests()
        {
            _mathOperationsContainer = new MathOperationsContainer();

            _mockParser            = new Mock <IParser>();
            _mockNotationConverter = new Mock <INotationConverter>();
            _mockMathProcessor     = new Mock <IMathProcessor>();

            _calculator = new MathCalculator(_mockParser.Object, _mockNotationConverter.Object, _mockMathProcessor.Object, _mathOperationsContainer);
        }
        private static MathOperation GetOperationByKeyword(ExpressionUnit item, IMathOperationsContainer mathOperationsContainer)
        {
            var operation = mathOperationsContainer.GetOperationOrDefault(item.Keyword);

            if (operation == null)
            {
                throw new ArgumentException("Invalid mathematical expression or unsupported operation.");
            }

            return(operation);
        }
Beispiel #5
0
        /// <summary>
        /// Execute operations in a mathematical expression
        /// </summary>
        /// <param name="expression">Mathematical expression</param>
        /// <param name="mathOperationsContainer">Avaliable math operations</param>
        /// <returns>Execution result</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="DivideByZeroException"></exception>
        /// <exception cref="NullReferenceException"></exception>
        public double Process(IEnumerable <ExpressionUnit> expression, IMathOperationsContainer mathOperationsContainer)
        {
            var stack = new Stack <double>();

            foreach (var item in expression)
            {
                if (item.Type == ExpressionUnitType.Number)
                {
                    stack.Push(double.Parse(item.Keyword, NumberStyles.Any, CultureInfo.InvariantCulture));
                    continue;
                }

                if (item.Type == ExpressionUnitType.Operation)
                {
                    var operation = GetOperationByKeyword(item, mathOperationsContainer);

                    operation.Operate(stack);
                }
            }

            return(stack.Peek());
        }
        /// <summary>
        /// Convert infix notation to reverse polish notation
        /// </summary>
        /// <param name="infixNotation">Infix notation</param>
        /// <param name="mathOperationsContainer">Avaliable math operations</param>
        /// <returns>Reverse polish notation</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="NullReferenceException"></exception>
        public IEnumerable <ExpressionUnit> ConvertToReversePolishNotation(IEnumerable <ExpressionUnit> infixNotation, IMathOperationsContainer mathOperationsContainer)
        {
            var stack  = new Stack <ExpressionUnit>();
            var result = new List <ExpressionUnit>();

            foreach (var item in infixNotation)
            {
                if (item.Type == ExpressionUnitType.Number)
                {
                    result.Add(item);

                    continue;
                }

                if (item.Type == ExpressionUnitType.LeftBracket)
                {
                    stack.Push(item);

                    continue;
                }

                if (item.Type == ExpressionUnitType.RightBracket)
                {
                    while (stack.Count != 0 && !(stack.Peek().Type == ExpressionUnitType.LeftBracket))
                    {
                        result.Add(stack.Pop());
                    }

                    if (stack.Count == 0)
                    {
                        throw new ArgumentException("Invalid mathematical expression or non-infix notation.");
                    }

                    stack.Pop();

                    continue;
                }

                var operation = GetOperationByKeyword(item, mathOperationsContainer);

                if (operation.Type == OperationType.Unary)
                {
                    stack.Push(item);

                    continue;
                }

                while (stack.Count() != 0)
                {
                    var peek = stack.Peek();
                    if (peek.Type != ExpressionUnitType.Operation)
                    {
                        break;
                    }

                    var peekOperation = GetOperationByKeyword(peek, mathOperationsContainer);

                    if (peekOperation.Type != OperationType.Unary && peekOperation.Priority <= operation.Priority)
                    {
                        break;
                    }

                    result.Add(stack.Pop());
                }

                stack.Push(item);
            }

            while (stack.Count() != 0)
            {
                var peek = stack.Peek();
                if ((peek.Type == ExpressionUnitType.Operation) && !(peek.Type == ExpressionUnitType.LeftBracket))
                {
                    result.Add(stack.Pop());
                }
                else
                {
                    throw new ArgumentException("Invalid mathematical expression or non-infix notation.");
                }
            }

            return(result);
        }
Beispiel #7
0
        private static bool TryParseExpressionUnit(string expressionItem, OperationType operationType, IMathOperationsContainer mathOperationsContainer, out ExpressionUnit expressionUnit)
        {
            var keyword = mathOperationsContainer.GetKeywordOrDefault(new OperationCharacteristics(expressionItem, operationType));

            if (!string.IsNullOrEmpty(keyword))
            {
                expressionUnit = new OperationExpressionUnit(expressionItem, keyword);

                return(true);
            }

            var leftBracketExpressionUnit = new LeftBracketExpressionUnit();

            if (expressionItem == leftBracketExpressionUnit.Keyword)
            {
                expressionUnit = leftBracketExpressionUnit;

                return(true);
            }

            var rightBracketExpressionUnit = new RightBracketExpressionUnit();

            if (expressionItem == rightBracketExpressionUnit.Keyword)
            {
                expressionUnit = rightBracketExpressionUnit;

                return(true);
            }

            expressionUnit = default(ExpressionUnit);

            return(false);
        }