/// <summary> /// Calculates value of the expression of many variables. /// </summary> /// <param name="variables">Variables</param> /// <returns>Value of the expression</returns> public double Calculate(params Var[] variables) { Stack stack = new Stack(); foreach (Token t in reversePolishNotation) { if (t.Type == TokenType.Number) { stack.Push(t); } else if (t.Type == TokenType.Operator) { string operand1Str = stack.Pop().Lexeme.Replace(',', '.'); string operand2Str = stack.Pop().Lexeme.Replace(',', '.'); double operand1 = double.Parse(operand1Str, CultureInfo.InvariantCulture); double operand2 = double.Parse(operand2Str, CultureInfo.InvariantCulture); double smallResult = operators[t.Lexeme](operand1, operand2); stack.Push(new Token(smallResult.ToString(CultureInfo.InvariantCulture), TokenType.Number)); } else if (t.Type == TokenType.Function) { string operandStr = stack.Pop().Lexeme.Replace(',', '.'); double operand = double.Parse(operandStr, CultureInfo.InvariantCulture); double smallResult = functions[t.Lexeme](operand); stack.Push(new Token(smallResult.ToString(CultureInfo.InvariantCulture), TokenType.Number)); } else if (t.Type == TokenType.Constant) { double constant = constants[t.Lexeme]; stack.Push(new Token(constant.ToString(CultureInfo.InvariantCulture), TokenType.Number)); } else if (t.Type == TokenType.Variable) { Token smallToken = new Token(); foreach (Var variable in variables) { if (t.Lexeme == variable.Name) { smallToken = new Token(variable.Value.ToString(CultureInfo.InvariantCulture), TokenType.Number); break; } } stack.Push(smallToken); } else { throw new ArgumentException("Bad expression string."); } } double result = double.Parse(stack.Pop().Lexeme, CultureInfo.InvariantCulture); return result; }
/// <summary> /// Adds a token to the top of stack. /// </summary> /// <param name="t">Token to add</param> public void Push(Token t) { tokens.Add(t); }
/// <summary> /// Parses a string of characters and converts it to sequence of tokens. /// </summary> /// <returns>Sequence of tokens</returns> private List<Token> GetTokens(string expression) { List<Token> tokens = new List<Token>(); bool isError; bool success; for (int i = 0; i < expression.Length; ++i) { isError = true; success = false; string number = ""; double num; while (double.TryParse(expression[i].ToString(CultureInfo.InvariantCulture), System.Globalization.NumberStyles.Number, CultureInfo.InvariantCulture, out num) || expression[i] == '.') { if (expression[i] == '.') { number += "."; } else { number += num.ToString(CultureInfo.InvariantCulture); } if (i < expression.Length - 1) { ++i; } else break; } if (number != "") { Token t = new Token(number, TokenType.Number); tokens.Add(t); success = true; isError = false; number = ""; } foreach (string s in operators.Keys) { if (expression[i].ToString(CultureInfo.InvariantCulture) == s) { if (isUnaryOparator(tokens)) { expression = expression.Insert(i, "0"); --i; } else { Token t = new Token(expression[i].ToString(CultureInfo.InvariantCulture), TokenType.Operator); tokens.Add(t); } success = true; isError = false; break; } } foreach (string s in functions.Keys) { if (success) { break; } string function = ""; int k = i; for (int j = 0; j < s.Length; ++j) { if (s[j] == expression[k]) { function += expression[k]; } if (k < expression.Length - 1) { ++k; } else break; } if (function == s) { Token t = new Token(function, TokenType.Function); tokens.Add(t); isError = false; success = true; i += function.Length - 1; break; } } foreach (string s in constants.Keys) { if (success) { break; } string constant = ""; int k = i; for (int j = 0; j < s.Length; ++j) { if (s[j] == expression[k]) { constant += expression[k]; } if (k < expression.Length - 1) { ++k; } else break; } if (constant == s) { Token t = new Token(constant, TokenType.Constant); tokens.Add(t); isError = false; success = true; i += constant.Length - 1; break; } } foreach (char c in variables) { if (success) { break; } if (expression[i] == c) { Token t = new Token(expression[i].ToString(CultureInfo.InvariantCulture), TokenType.Variable); tokens.Add(t); isError = false; success = true; break; } } if (isError) { throw new ArgumentException("Bad expression string."); } } return tokens; }