Создание калькулятора RPN с использованием c#. NET с деревьями выражений - PullRequest
1 голос
/ 20 января 2020

Я новичок в деревьях выражений и давно не делал c#. Мне нужно создать калькулятор обратной записи poli sh, используя деревья выражений.

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

Expression<Func<double, double, double, double>> calc = (x, y, z) => x + y - z;
 //sample input 11 6 5 4 + - / 7 * 2 2 2 + - 

    //my expression class
 class Expression : ExpressionVisitor
{
    Stack<int> nums = new Stack<int>();
    Stack<char> ops = new Stack<char>();



    public override Expression Visit(Expression node)
    {
        if (node == null)
        {
            return null;
        }
        switch (node.NodeType)
        {

            case ExpressionType.Add:
                return this.VisitBinary((BinaryExpression)node); 
            case ExpressionType.Subtract:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Multiply:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Divide:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Power:
                return this.VisitBinary((BinaryExpression)node);
            default:
                return base.Visit(node);

        }
    }


    protected override Expression VisitBinary(BinaryExpression node)
    {

        var rightSide = this.Visit(node.rightSide);


        var leftSide = this.Visit(node.leftSide);
        switch (node.NodeType)
        {
            case ExpressionType.Add:
                return Expression.MakeBinary(ExpressionType.Add, leftSide, rightSide);
            case ExpressionType.Subtract:
                return Expression.MakeBinary(ExpressionType.Subtract, leftSide, rightSide);
            case ExpressionType.Multiply:
              return  Expression.MakeBinary(ExpressionType.Multiply, leftSide, rightSide);
            case ExpressionType.Divide:
              return  Expression.MakeBinary(ExpressionType.Divide, leftSide, rightSide);
            case ExpressionType.Power:
                return Expression.MakeBinary(ExpressionType.Power, leftSide, rightSide);

            default:
                return base.VisitBinary(node);
        }

//main class    
static void Main(string[] args)
    {


        var visitor = new Expression();
        string input = Console.ReadLine();
        string[] rpnTokens = input.Split(' ');
        Expression<Func<double, double, double, double>> calc = (x, y, z) => x + y - z;

        Console.WriteLine("result: " + calc);


    }

1 Ответ

0 голосов
/ 21 февраля 2020

С помощью обратного полиса sh Обозначение вводится пользователем в том порядке, в котором он был введен.

  • Разделение ввода пользователя на последовательность операндов и операторов (назовите их токенами).
  • Создайте один пустой стек для хранения операндов и промежуточных результатов.
  • Действуйте на пользовательском вводе (то есть 'call it' ) в Порядок следования (для вашего примера ввода последовательность будет 11, затем 6, затем 5 и т. д. c.)
    • Для операнда pu sh операнд в стеке.
    • Для оператора
      • Поп-операнд 2 со стека
      • Поп-операнд 1 со стека
      • Pu sh Результат оператора, примененный к операнду 1 и операнду 2 в стек
  • После активации последнего токена в стеке должно остаться одно значение; результат выражения.

Использует ли это дерево выражений для создания калькулятора RPN? Входная строка эквивалентна дереву выражений (см. пример дерева выражений ). Он кодирует ту же информацию; а именно, последовательность операций. «5» и «4» должны быть добавлены до того, как результат может быть вычтен из «6» и т. Д. c. Поэтому, возможно, лучший способ сказать, что эквивалент дерева выражений используется в качестве входных данных для калькулятора RPN.


Пример с использованием примера ввода из фрагмента кода.

Empty stack              {}
Push 11                  {11}
Push 6                   {11, 6}
Push 5                   {11, 6, 5}
Push 4                   {11, 6, 5, 4}

Pop operand 2, = 4       {11, 6, 5}
Pop operand 1, = 5       {11, 6}
Push + operator result   {11, 6, 9}

Pop operand 2 = 9        {11, 6}
Pop operand 1 = 6        {11}
Push - operator result   {11, -3}

Pop operand 2 = -3       {11}
Pop operand 1 = 11       {}
Push / operator result   {-11/3}

Push 7                   {-11/3, 7}

Pop operand 2 = 7        {-11/3}
Pop operand 1 = -11/3    {}
Push * operator result   {-77/3}

Push 2                   {-77/3, 2}
Push 2                   {-77/3, 2, 2}
Push 2                   {-77/3, 2, 2, 2}

Pop operand 2 = 2        {-77/3, 2, 2}
Pop operand 1 = 2        {-77/3, 2}
Push + operator result   {-77/3, 2, 4}

Pop operand 2 = 4        {-77/3, 2}
Pop operand 1 = 2        {-77/3}
Push - operator result   {-77/3, -2}

NOTE:  There are two values left on the stack, so the expression is incomplete.
Let's add a '+' operator to complete it.

Pop operand 2 = -2       {-77/3}
Pop operand 1 = -77/3    {}
Push + operator result   {-83/3}

So, there are no more tokens *and* there is one value on the stack.  Success!

Pop final result = -83/3 {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...