archangelmihail

CalculateExpression

Jan 11th, 2014
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.42 KB | None | 0 0
  1. using System;
  2. using System.Text;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.Threading;
  7. /*  * Write a program that calculates the value of given arithmetical expression.
  8.  * The expression can contain the following elements only:
  9.     Real numbers, e.g. 5, 18.33, 3.14159, 12.6
  10.     Arithmetic operators: +, -, *, / (standard priorities)
  11.     Mathematical functions: ln(x), sqrt(x), pow(x,y)
  12.     Brackets (for changing the default priorities)
  13.     Examples: 3 + 4 * 2/(1-5)
  14.     (3+5.3) * 2.7 - ln(22) / pow(2.2, -1.7)  ~ 10.6
  15.     pow(2, 3.14) * (3 - (3 * sqrt(2) - 3.2) + 1.5*0.3)  ~ 21.22
  16.     Hint: Use the classical "shunting yard" algorithm and "reverse Polish notation".    */
  17.  
  18. class CalculateExpression
  19. {
  20.     public static List<char> arithmeticOperations = new List<char>() { '+', '-', '*', '/' };
  21.     public static List<char> brackets = new List<char>() { '(', ')' };
  22.     public static List<string> functions = new List<string>() { "pow", "ln" , "sqrt" };
  23.  
  24.     public static List<string> SeparateTokens(string input)
  25.     {
  26.         var result = new List<string>();
  27.         var number = new StringBuilder();
  28.         for (int i = 0; i < input.Length; i++)
  29.         {
  30.             if (input[i] == '-' && (i == 0 || input [i-1] == ',' || input[i] == '('))
  31.             {
  32.                 number.Append('-');
  33.             }
  34.             else if (char.IsDigit(input[i]) || input[i] == '.')
  35.             {
  36.                 number.Append(input[i]);
  37.             }
  38.             else if (!char.IsDigit(input[i]) && input[i] != '.' && number.Length != 0)
  39.             {
  40.                 result.Add(number.ToString());
  41.                 number.Clear();
  42.                 i--;
  43.             }
  44.             else if (brackets.Contains(input[i]))
  45.             {
  46.                 result.Add(input[i].ToString());
  47.             }
  48.             else if (arithmeticOperations.Contains(input[i]))
  49.             {
  50.                 result.Add(input[i].ToString());
  51.             }
  52.             else if (input[i] == ',')
  53.             {
  54.                 result.Add(",");
  55.             }
  56.             else if( (i + 1) < input.Length  && input.Substring(i,2).ToLower()== "ln")
  57.             {
  58.                 result.Add("ln");
  59.                 i++;
  60.             }
  61.             else if ((i + 2) < input.Length && input.Substring(i, 3).ToLower() == "pow")
  62.             {
  63.                 result.Add("pow");
  64.                 i+=2;
  65.             }
  66.             else if ((i + 3) < input.Length && input.Substring(i, 4).ToLower() == "sqrt")
  67.             {
  68.                 result.Add("sqrt");
  69.                 i += 3;
  70.             }
  71.             else
  72.             {
  73.                 throw new ArgumentException("Invalid Expression!");
  74.             }
  75.         }
  76.         if (number.Length != 0)
  77.         {
  78.             result.Add(number.ToString());
  79.         }
  80.         return result;
  81.     }
  82.     public static int Precedence(string arithmeticOperator)
  83.     {
  84.         if (arithmeticOperator == "+" || arithmeticOperator == "-")
  85.         {
  86.             return 1;
  87.         }
  88.         return 2;
  89.     }
  90.     public static void PutInvariantCulture()
  91.     {
  92.         Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
  93.     }
  94.     public static Queue<string> ConvertToReversePolishRotation(List<string> tokens)
  95.     {
  96.         Stack<string> stack = new Stack<string>();
  97.         Queue<string> queue = new Queue<string>();
  98.         for (int i = 0; i < tokens.Count; i++)
  99.         {
  100.             var currentToken = tokens[i];
  101.             double number;
  102.             if (double.TryParse(currentToken, out number))
  103.             {
  104.                 queue.Enqueue(currentToken);
  105.             }
  106.             else if (functions.Contains(currentToken))
  107.             {
  108.                 stack.Push(currentToken);
  109.             }
  110.             else if (currentToken == ",")
  111.             {
  112.                 if (!stack.Contains("(") || stack.Count == 0)
  113.                 {
  114.                     throw new ArgumentException("Invalid brackets or function separator!");
  115.                 }
  116.                 while (stack.Peek() != "(")
  117.                 {
  118.                     queue.Enqueue(stack.Pop());
  119.                 }
  120.             }
  121.             else if (arithmeticOperations.Contains(currentToken[0]))
  122.             {
  123.                 while (stack.Count != 0 && arithmeticOperations.Contains(stack.Peek()[0]) && Precedence(currentToken) <= Precedence(stack.Peek()))
  124.                 {
  125.                     queue.Enqueue(stack.Pop());
  126.                 }
  127.                 stack.Push(currentToken);
  128.             }
  129.             else if (currentToken == "(")
  130.             {
  131.                 stack.Push("(");
  132.             }
  133.             else if (currentToken == ")")
  134.             {
  135.                 if (!stack.Contains("(") || stack.Count == 0)
  136.                 {
  137.                     throw new ArgumentException("Invalid brackets position!");
  138.                 }
  139.                 while (stack.Peek() != "(")
  140.                 {
  141.                     queue.Enqueue(stack.Pop());
  142.                 }
  143.                 stack.Pop();
  144.                 if (stack.Count !=0 && functions.Contains(stack.Peek()))
  145.                 {
  146.                     queue.Enqueue(stack.Pop());
  147.                 }
  148.             }
  149.         }
  150.         while (stack.Count != 0)
  151.         {
  152.             if (brackets.Contains(stack.Peek()[0]))
  153.             {
  154.                 throw new ArgumentException("Invalid bracket position");
  155.             }
  156.             queue.Enqueue(stack.Pop());
  157.         }
  158.         return queue;
  159.     }
  160.     public static double GetResultFromRPN(Queue<string> queue)
  161.     {
  162.         Stack<double> stack = new Stack<double>();
  163.         while (queue.Count !=0)
  164.         {
  165.             string currentToken = queue.Dequeue();
  166.             double number;
  167.             if (double.TryParse(currentToken, out number))
  168.             {
  169.                 stack.Push(number);
  170.             }
  171.             else if (arithmeticOperations.Contains(currentToken[0]) || functions.Contains(currentToken))
  172.             {
  173.                 if (currentToken == "+")
  174.                 {
  175.                     if (stack.Count < 2)
  176.                     {
  177.                         throw new ArgumentException("Invalid Expression!");
  178.                     }
  179.                     else
  180.                     {
  181.                         double firstValue = stack.Pop();
  182.                         double secondValue = stack.Pop();
  183.                         stack.Push(firstValue + secondValue);
  184.                     }
  185.                 }
  186.                 else if (currentToken == "-")
  187.                 {
  188.                     if (stack.Count < 2)
  189.                     {
  190.                         throw new ArgumentException("Invalid Expression!");
  191.                     }
  192.                     else
  193.                     {
  194.                         double firstValue = stack.Pop();
  195.                         double secondValue = stack.Pop();
  196.                         stack.Push(secondValue - firstValue);
  197.                     }
  198.                 }
  199.                 else if (currentToken == "*")
  200.                 {
  201.                     if (stack.Count < 2)
  202.                     {
  203.                         throw new ArgumentException("Invalid Expression!");
  204.                     }
  205.                     else
  206.                     {
  207.                         double firstValue = stack.Pop();
  208.                         double secondValue = stack.Pop();
  209.                         stack.Push(firstValue * secondValue);
  210.                     }
  211.                 }
  212.                 else if (currentToken == "/")
  213.                 {
  214.                     if (stack.Count < 2)
  215.                     {
  216.                         throw new ArgumentException("Invalid Expression!");
  217.                     }
  218.                     else
  219.                     {
  220.                         double firstValue = stack.Pop();
  221.                         double secondValue = stack.Pop();
  222.                         stack.Push(secondValue/firstValue);
  223.                     }
  224.                 }
  225.                 else if (currentToken == "pow")
  226.                 {
  227.                     if (stack.Count < 2)
  228.                     {
  229.                         throw new ArgumentException("Invalid Expression!");
  230.                     }
  231.                     else
  232.                     {
  233.                         double firstValue = stack.Pop();
  234.                         double secondValue = stack.Pop();
  235.                         stack.Push(Math.Pow(secondValue,firstValue));
  236.                     }
  237.                 }
  238.                 else if (currentToken == "sqrt")
  239.                 {
  240.                     if (stack.Count < 1)
  241.                     {
  242.                         throw new ArgumentException("Invalid Expression!");
  243.                     }
  244.                     else
  245.                     {
  246.                         double value = stack.Pop();
  247.                         stack.Push(Math.Sqrt(value));
  248.                     }
  249.                 }
  250.                 else if (currentToken == "ln")
  251.                 {
  252.                     if (stack.Count < 1)
  253.                     {
  254.                         throw new ArgumentException("Invalid Expression!");
  255.                     }
  256.                     else
  257.                     {
  258.                         double value = stack.Pop();
  259.                         stack.Push(Math.Log(value));
  260.                     }
  261.                 }
  262.             }
  263.         }
  264.         if (stack.Count == 1)
  265.         {
  266.             return stack.Pop();
  267.         }
  268.         else
  269.         {
  270.             throw new ArgumentException("Invalid Expression!");
  271.         }
  272.     }
  273.     public static void StartCalculating()
  274.     {
  275.         Console.WriteLine("Enter valid expression or \"end\": ");
  276.         string input = Console.ReadLine().Trim();
  277.         while (input.ToLower() != "end")
  278.         {
  279.             try
  280.             {
  281.                 input = input.Replace(" ", string.Empty);
  282.                 var separatedTokens = SeparateTokens(input);
  283.                 var reversePolishNotation = ConvertToReversePolishRotation(separatedTokens);
  284.                 var result = GetResultFromRPN(reversePolishNotation);
  285.                 Console.WriteLine(result);
  286.             }
  287.             catch (ArgumentException exc)
  288.             {
  289.                 Console.WriteLine(exc.Message);
  290.             }
  291.             Console.WriteLine("Enter valid expression or \"end\": ");
  292.             input = Console.ReadLine().Trim();
  293.         }
  294.     }
  295.     static void Main()
  296.     {
  297.         PutInvariantCulture();
  298.         StartCalculating();
  299.     }
  300. }
Advertisement
Add Comment
Please, Sign In to add comment