Как сделать калькулятор, который учитывает приоритет операций?

Для создания калькулятора, который учитывает приоритет операций, мы можем использовать стек (stack) для реализации алгоритма обратной польской записи (Reverse Polish Notation, RPN).

Первым шагом будет разбить входное выражение на отдельные токены, такие как числа и операторы. Для этого мы можем использовать метод Split() и регулярное выражение для распознавания чисел и операторов.

string input = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
string[] tokens = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

Затем мы создаем стек для хранения операторов и промежуточного результата. Мы также создаем выходную очередь для хранения выходной последовательности токенов.

Stack<string> operators = new Stack<string>();
Queue<string> output = new Queue<string>();

Далее мы проходим через каждый токен и выполняем соответствующие операции:

1. Если токен - число, мы добавляем его в выходную очередь.
2. Если токен - оператор, мы проверяем его приоритет с операторами на вершине стека и помещаем операторы с более высоким приоритетом в выходную очередь. Затем мы помещаем текущий оператор в стек.
3. Если токен - открывающая скобка, мы помещаем ее в стек.
4. Если токен - закрывающая скобка, мы извлекаем операторы из стека и помещаем их в выходную очередь до тех пор, пока не встретим открывающую скобку. Затем мы удаляем открывающую скобку из стека.
5. Если стек не пустой, мы извлекаем все оставшиеся операторы и помещаем их в выходную очередь.
6. Наконец, мы вычисляем результат, используя алгоритм обратной польской записи. Мы создаем еще один стек, в котором будем хранить операнды. Мы проходим по каждому элементу выходной очереди и применяем соответствующую операцию. Результат помещаем в стек операндов.

Stack<double> operands = new Stack<double>();

foreach (string token in output)
{
    if (IsNumber(token))
    {
        operands.Push(double.Parse(token));
    }
    else if (IsOperator(token))
    {
        double operand2 = operands.Pop();
        double operand1 = operands.Pop();
        double result = EvaluateOperation(operand1, operand2, token);
        operands.Push(result);
    }
}

double finalResult = operands.Pop();
Console.WriteLine("Result: " + finalResult);

Функции IsNumber() и IsOperator() можно использовать для проверки токенов на число и оператор. Функция EvaluateOperation() должна выполнять соответствующую операцию в зависимости от оператора.

bool IsNumber(string token)
{
    double result;
    return double.TryParse(token, out result);
}

bool IsOperator(string token)
{
    return token == "+" || token == "-" || token == "*" || token == "/" || token == "^";
}

double EvaluateOperation(double operand1, double operand2, string operator)
{
    switch (operator)
    {
        case "+":
            return operand1 + operand2;
        case "-":
            return operand1 - operand2;
        case "*":
            return operand1 * operand2;
        case "/":
            return operand1 / operand2;
        case "^":
            return Math.Pow(operand1, operand2);
        default:
            throw new ArgumentException("Invalid operator: " + operator);
    }
}

Таким образом, мы можем создать калькулятор, который учитывает приоритет операций, используя алгоритм обратной польской записи и стек для хранения операторов и операндов.