Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace MathExpression
- {
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Text;
- using System.Threading;
- public class ExpressionCalculator
- {
- public static List<char> arithmeticOperations = new List<char>() { '+', '-', '*', '/' };
- public static List<char> brackets = new List<char>() { '(', ')' };
- public static List<string> functions = new List<string>() { "pow", "sqrt", "ln", "sin", "cos", "tan" };
- public static readonly Dictionary<string, double> constants = InitConstants();
- private static Dictionary<string, double> InitConstants()
- {
- Dictionary<string, double> dic = new Dictionary<string, double>();
- dic.Add("E", 2.71828182846);
- dic.Add("PI", 3.14159265359);
- return dic;
- }
- public static List<string> SeparateTokens(string input)
- {
- var result = new List<string>();
- var number = new StringBuilder();
- for (int i = 0; i < input.Length; i++)
- {
- if (input[i] == '-' && (i == 0 || input[i - 1] == ',' || input[i - 1] == '('))
- {
- number.Append('-');
- }
- else if (char.IsDigit(input[i]) || input[i] == '.')
- {
- number.Append(input[i]);
- }
- else if (!char.IsDigit(input[i]) && input[i] != '.' && number.Length != 0)
- {
- result.Add(number.ToString());
- number.Clear();
- i--;
- }
- else if (brackets.Contains(input[i]))
- {
- result.Add(input[i].ToString());
- }
- else if (arithmeticOperations.Contains(input[i]))
- {
- result.Add(input[i].ToString());
- }
- else if (input[i] == ',')
- {
- result.Add(",");
- }
- else if (i + 1 < input.Length && input.Substring(i, 2).ToLower() == "ln")
- {
- result.Add("ln");
- i++;
- }
- else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "pow")
- {
- result.Add("pow");
- i += 2;
- }
- else if (i + 3 < input.Length && input.Substring(i, 4).ToLower() == "sqrt")
- {
- result.Add("sqrt");
- i += 3;
- }
- else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "sin")
- {
- result.Add("sin");
- i += 2;
- }
- else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "cos")
- {
- result.Add("cos");
- i += 2;
- }
- else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "tan")
- {
- result.Add("tan");
- i += 2;
- }
- else if (i + 1 < input.Length && input.Substring(i, 2).ToLower() == "pi")
- {
- result.Add("PI");
- i++;
- }
- else if (input[i].ToString().ToLower() == "e")
- {
- result.Add("E");
- }
- else
- {
- throw new ArgumentException("Invalid expression");
- }
- }
- if (number.Length != 0)
- {
- result.Add(number.ToString());
- }
- return result;
- }
- public static int Precedence(string arithmeticOperator)
- {
- if (arithmeticOperator == "+" || arithmeticOperator == "-")
- {
- return 1;
- }
- else
- {
- return 2;
- }
- }
- public static Queue<string> ConvertToReversePolishNotation(List<string> tokens)
- {
- Stack<string> stack = new Stack<string>();
- Queue<string> queue = new Queue<string>();
- for (int i = 0; i < tokens.Count; i++)
- {
- var currentToken = tokens[i];
- double number;
- if (double.TryParse(currentToken, out number))
- {
- queue.Enqueue(currentToken);
- }
- else if (constants.ContainsKey(currentToken.ToUpper()))
- {
- queue.Enqueue(constants[currentToken.ToUpper()].ToString());
- }
- else if (functions.Contains(currentToken))
- {
- stack.Push(currentToken);
- }
- else if (currentToken == ",")
- {
- if (!stack.Contains("(") || stack.Count == 0)
- {
- throw new ArgumentException("Invalid brackets or function separator");
- }
- while (stack.Peek() != "(")
- {
- queue.Enqueue(stack.Pop());
- // if not working => you may need to pop the "("
- }
- }
- else if (arithmeticOperations.Contains(currentToken[0]))
- {
- // if not working => refactor logic for currentToken
- while (stack.Count != 0 && arithmeticOperations.Contains(stack.Peek()[0]) && Precedence(currentToken) <= Precedence(stack.Peek()))
- {
- queue.Enqueue(stack.Pop());
- }
- stack.Push(currentToken);
- }
- else if (currentToken == "(")
- {
- stack.Push("(");
- }
- else if (currentToken == ")")
- {
- if (!stack.Contains("(") || stack.Count == 0)
- {
- throw new ArgumentException("Invalid brackets position");
- }
- while (stack.Peek() != "(")
- {
- queue.Enqueue(stack.Pop());
- }
- stack.Pop();
- if (stack.Count != 0 && functions.Contains(stack.Peek()))
- {
- queue.Enqueue(stack.Pop());
- }
- }
- }
- while (stack.Count != 0)
- {
- if (brackets.Contains(stack.Peek()[0]))
- {
- throw new ArgumentException("Invalid brackets position");
- }
- queue.Enqueue(stack.Pop());
- }
- return queue;
- }
- public static double GetResultFromRPN(Queue<string> queue)
- {
- Stack<double> stack = new Stack<double>();
- while (queue.Count != 0)
- {
- string currentToken = queue.Dequeue();
- double number;
- if (double.TryParse(currentToken, out number))
- {
- stack.Push(number);
- }
- else if (arithmeticOperations.Contains(currentToken[0]) || functions.Contains(currentToken) || constants.ContainsKey(currentToken.ToUpper()))
- {
- if (currentToken == "+")
- {
- if (stack.Count < 2)
- {
- throw new ArgumentException("Invalid expression");
- }
- double firstValue = stack.Pop();
- double secondValue = stack.Pop();
- stack.Push(firstValue + secondValue);
- }
- else if (currentToken == "-")
- {
- if (stack.Count < 2)
- {
- throw new ArgumentException("Invalid expression");
- }
- double firstValue = stack.Pop();
- double secondValue = stack.Pop();
- stack.Push(secondValue - firstValue);
- }
- else if (currentToken == "*")
- {
- if (stack.Count < 2)
- {
- throw new ArgumentException("Invalid expression");
- }
- double firstValue = stack.Pop();
- double secondValue = stack.Pop();
- stack.Push(secondValue * firstValue);
- }
- else if (currentToken == "/")
- {
- if (stack.Count < 2)
- {
- throw new ArgumentException("Invalid expression");
- }
- double firstValue = stack.Pop();
- double secondValue = stack.Pop();
- stack.Push(secondValue / firstValue);
- }
- else if (currentToken == "pow")
- {
- if (stack.Count < 2)
- {
- throw new ArgumentException("Invalid expression");
- }
- double firstValue = stack.Pop();
- double secondValue = stack.Pop();
- stack.Push(Math.Pow(secondValue, firstValue));
- }
- else if (currentToken == "sqrt")
- {
- if (stack.Count < 1)
- {
- throw new ArgumentException("Invalid expression");
- }
- double value = stack.Pop();
- stack.Push(Math.Sqrt(value));
- }
- else if (currentToken == "ln")
- {
- if (stack.Count < 1)
- {
- throw new ArgumentException("Invalid expression");
- }
- double value = stack.Pop();
- stack.Push(Math.Log(value));
- }
- else if (currentToken == "sin")
- {
- if (stack.Count < 1)
- {
- throw new ArgumentException("Invalid expression");
- }
- double value = stack.Pop();
- stack.Push(Math.Sin(value));
- }
- else if (currentToken == "cos")
- {
- if (stack.Count < 1)
- {
- throw new ArgumentException("Invalid expression");
- }
- double value = stack.Pop();
- stack.Push(Math.Cos(value));
- }
- else if (currentToken == "tan")
- {
- if (stack.Count < 1)
- {
- throw new ArgumentException("Invalid expression");
- }
- double value = stack.Pop();
- stack.Push(Math.Tan(value));
- }
- }
- }
- if (stack.Count == 1)
- {
- return stack.Pop();
- }
- else
- {
- throw new ArgumentException("Invalid expression");
- }
- }
- public static void StartCalculating()
- {
- string input = Console.ReadLine().Trim();
- while (input.ToLower() != "end")
- {
- try
- {
- string trimmedInput = input.Replace(" ", string.Empty);
- var separatedTokens = SeparateTokens(trimmedInput);
- var reversePolishNotation = ConvertToReversePolishNotation(separatedTokens);
- var finalResult = GetResultFromRPN(reversePolishNotation);
- Console.WriteLine(finalResult);
- }
- catch (ArgumentException exeption)
- {
- Console.WriteLine(exeption.Message);
- }
- input = Console.ReadLine().Trim();
- }
- }
- public static void Main()
- {
- StartCalculating();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement