Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace POZcalc
- {
- class RPN
- {
- //Метод Calculate принимает выражение в виде строки и возвращает результат, в своей работе использует другие методы класса
- static public double Calculate(string input)
- {
- string output = GetExpression(input); //Преобразовываем выражение в постфиксную запись
- double result = Counting(output); //Решаем полученное выражение
- return result; //Возвращаем результат
- }
- //Метод, преобразующий входную строку с выражением в постфиксную запись
- static private string GetExpression(string input)
- {
- string output = string.Empty; //Строка для хранения выражения
- Stack<char> operStack = new Stack<char>(); //Стек для хранения операторов
- for (int i = 0; i < input.Length; i++) //Для каждого символа в входной строке
- {
- //Разделители пропускаем
- if (IsDelimeter(input[i]))
- continue; //Переходим к следующему символу
- //Если символ - цифра, то считываем все число
- if (Char.IsDigit(input[i])) //Если цифра
- {
- //Читаем до разделителя или оператора, что бы получить число
- while (!IsDelimeter(input[i]) && !IsOperator(input[i]))
- {
- output += input[i]; //Добавляем каждую цифру числа к нашей строке
- i++; //Переходим к следующему символу
- if (i == input.Length) break; //Если символ - последний, то выходим из цикла
- }
- output += " "; //Дописываем после числа пробел в строку с выражением
- i--; //Возвращаемся на один символ назад, к символу перед разделителем
- }
- //Если символ - оператор
- if (IsOperator(input[i])) //Если оператор
- {
- if (input[i] == '(') //Если символ - открывающая скобка
- operStack.Push(input[i]); //Записываем её в стек
- else if (input[i] == ')') //Если символ - закрывающая скобка
- {
- //Выписываем все операторы до открывающей скобки в строку
- char s = operStack.Pop();
- while (s != '(')
- {
- output += s.ToString() + ' ';
- s = operStack.Pop();
- }
- }
- else //Если любой другой оператор
- {
- if (operStack.Count > 0) //Если в стеке есть элементы
- if (GetPriority(input[i]) <= GetPriority(operStack.Peek())) //И если приоритет нашего оператора меньше или равен приоритету оператора на вершине стека
- output += operStack.Pop().ToString() + " "; //То добавляем последний оператор из стека в строку с выражением
- operStack.Push(char.Parse(input[i].ToString())); //Если стек пуст, или же приоритет оператора выше - добавляем операторов на вершину стека
- }
- }
- }
- //Когда прошли по всем символам, выкидываем из стека все оставшиеся там операторы в строку
- while (operStack.Count > 0)
- output += operStack.Pop() + " ";
- Console.WriteLine("Обратная польская запись {0}",output);
- return output; //Возвращаем выражение в постфиксной записи
- }
- //Метод, вычисляющий значение выражения, уже преобразованного в постфиксную запись
- static private double Counting(string input)
- {
- double result = 0; //Результат
- Stack<double> temp = new Stack<double>(); //Временный стек для решения
- for (int i = 0; i < input.Length; i++) //Для каждого символа в строке
- {
- //Если символ - цифра, то читаем все число и записываем на вершину стека
- if (Char.IsDigit(input[i]))
- {
- string a = string.Empty;
- while (!IsDelimeter(input[i]) && !IsOperator(input[i])) //Пока не разделитель
- {
- a += input[i]; //Добавляем
- i++;
- if (i == input.Length) break;
- }
- temp.Push(double.Parse(a)); //Записываем в стек
- i--;
- }
- else if (IsOperator(input[i])) //Если символ - оператор
- {
- //Берем два последних значения из стека
- double a = temp.Pop();
- double b = temp.Pop();
- switch (input[i]) //И производим над ними действие, согласно оператору
- {
- case '+':
- result = b + a;
- Console.Write("{0} + {1} = {2}\n", b, a, result);
- break;
- case '-':
- result = b - a;
- Console.Write("{0} - {1} = {2}\n", b, a, result);
- break;
- case '*':
- result = b * a;
- Console.Write("{0} * {1} = {2}\n", b, a, result);
- break;
- case '/':
- if (a == 0)
- Console.WriteLine("Деление на ноль");
- else
- {
- result = b / a;
- Console.Write("{0} / {1} = {2}\n", b, a, result);
- }
- break;
- case '^':
- result = double.Parse(Math.Pow(double.Parse(b.ToString()), double.Parse(a.ToString())).ToString());
- Console.Write("{0} ^ {1} = {2}\n", b, a, result);
- break;
- }
- temp.Push(result); //Результат вычисления записываем обратно в стек
- }
- }
- return temp.Peek(); //Забираем результат всех вычислений из стека и возвращаем его
- }
- static private bool IsDelimeter(char c)
- {
- if ((" =".IndexOf(c) != -1))
- return true;
- return false;
- }
- static private bool IsOperator(char с)
- {
- if (("+-/*^()".IndexOf(с) != -1))
- return true;
- return false;
- }
- static private byte GetPriority(char s)
- {
- switch (s)
- {
- case '(': return 0;
- case ')': return 1;
- case '+': return 2;
- case '-': return 3;
- case '*': return 4;
- case '/': return 4;
- case '^': return 5;
- default: return 6;
- }
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("Введите выражение: ");
- string s = Console.ReadLine();
- char[] s1 = s.ToCharArray();
- int[] chars = new int[s.Length];
- for (int i = 0; i < s.Length; i++)
- chars[i] = -1;
- for (int i = 0; i < s.Length; i++)
- {
- if (Char.IsLetter(s[i]) == true)
- {
- int k = 0;
- int temp = 0;
- for(int j=0; j<i;j++)
- {
- if (s[j] == s[i])
- {
- k++;
- temp = j;
- }
- }
- if (k == 0)
- {
- Console.Write("{0} = ", s[i]);
- chars[i] = Convert.ToInt32(Console.ReadLine());
- }
- else
- chars[i] = chars[temp];
- }
- }
- string finalstring = "";
- char[] Chars = s.ToCharArray();
- for (int i = 0; i < s.Length; i++)
- if (chars[i] != -1)
- finalstring += chars[i].ToString();
- else
- finalstring += Chars[i];
- Console.WriteLine("Результат: {0}",RPN.Calculate(finalstring));
- Console.ReadKey();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement