Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/137: Рейтинг темы: голосов - 137, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 21.03.2011
Сообщений: 26

Калькулятор: сделать обратную польскую запись

20.04.2011, 21:44. Показов 26278. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
есть инженерный калькулятор, нужно сделать обратную польскую запись или другими словами сделать приоритетность действий...помогите пожалуйста
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.04.2011, 21:44
Ответы с готовыми решениями:

Преобразование математической формулы в обратную польскую запись
Нужен исходник по переводу математической формулы типа "a+b*c(e/d)" в обратную польскую используя стек.

Ошибка в алгоритме преобразования выражения в обратную польскую запись
Метод OPLConvert принимает выражение в виде строки, например "2+2*2". Пока что без учета приоритета операторов хочу чтобы мне мой метод...

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

12
389 / 304 / 67
Регистрация: 10.07.2010
Сообщений: 802
21.04.2011, 00:22
парень ты что издеваешься)) это и есть самое сложное, что может быть в инженерном калькуляторе..по сути это как раз самое главное в этой программе) и это код далеко не из двух строк, потому как криворукий пользователь имеет богатую фантазию, а программисту надо все это учесть...Я бы на твоем месте смотрел в сторону динамической компиляции наверно или чего то такого, если не хочется особо парится

Добавлено через 1 час 50 минут

Не по теме:

кстати извиняюсь, ведь вы девушка) привык к тому что в основном здесь одни парни...

0
 Аватар для Konctantin
970 / 773 / 171
Регистрация: 12.04.2009
Сообщений: 1,700
21.04.2011, 10:49
пример калькулятора с динамической компиляцией
0
389 / 304 / 67
Регистрация: 10.07.2010
Сообщений: 802
22.04.2011, 00:29
блин ну вы меня зацепили этим вопросом) сегодня как только с универа вечерком вернулся, так сразу алгоритм стал терзать, вот собственно то что получилось...вроде проверил, считает все исправно. код вылаживаю для тех кому интересно, однако думаю он только под копипаст годится ибо разобрать в нем хоть что то думаю невероято тяжело) Хотя может кто то и осилит..в любом случае для начала почитайте википедию, там на удивление хорошо описана суть алгоритма.
В коде 2-а метода. Один(Create_OPZ) формирует массив операндов из инфиксной нотации в обратную польскую запись, а второй(Solution) собственно считает выражение. Все выполняемые действия выводятся в RichTextBox. Поддерживаются только стандартные операции(+, -, *, /, ^). Кстати возможны ошибки, хоть я на них и не наткнулся.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
        public string Create_OPZ(string input_string)
        { 
            string[] output_string=new string[0];
            string[] stack=new string[0];
            
            int k = 0;
            for (int i = 0; i < input_string.Length; i++)
            {
                string temp = "";
                if (input_string[i] == '-' && ((i > 0 && !Char.IsDigit(input_string[i - 1])) || i == 0))
                {
                    i++;
                    temp += "-";
                }
                if (Char.IsDigit(input_string[i]))
                {                    
                    while (i < input_string.Length&&Char.IsDigit(input_string[i]))
                        temp += input_string[i++].ToString();
                    i--;
                    Array.Resize(ref output_string, output_string.Length + 1);
                    output_string[output_string.Length - 1] = temp;
                }
                if (input_string[i] == '+' || input_string[i] == '-')
                {
                m:
                    if (stack.Length != 0)
                    {
                        if (stack[stack.Length - 1] == "(")
                        {
                            Array.Resize(ref stack, stack.Length + 1);
                            stack[stack.Length - 1] = input_string[i].ToString();
                        }
                        else
                        {
                            Array.Resize(ref output_string, output_string.Length + 1);
                            output_string[output_string.Length - 1] = stack[stack.Length - 1];
                            Array.Resize(ref stack, stack.Length - 1);
                            goto m;
                        }
                        stack[stack.Length - 1] = input_string[i].ToString();
                    }
                    else
                    {
                        Array.Resize(ref stack, stack.Length + 1);
                        stack[stack.Length - 1] = input_string[i].ToString();
                    }
                }
                if (input_string[i] == '*' || input_string[i] == '/')
                {
               
                    if (stack.Length != 0)
                    {
                       
                      if (stack[stack.Length - 1] != "*" && stack[stack.Length - 1] != "/")
                        {
                            Array.Resize(ref stack, stack.Length + 1);
                            stack[stack.Length - 1] = input_string[i].ToString();
                        }
                        else
                        {
                            Array.Resize(ref output_string, output_string.Length + 1);
                            output_string[output_string.Length - 1] = stack[stack.Length - 1];
                            stack[stack.Length - 1] = input_string[i].ToString();
                            
                        }
                        
                    }
                    else
                    {
                        Array.Resize(ref stack, stack.Length + 1);
                        stack[stack.Length - 1] = input_string[i].ToString();
                    }
                }
                if (input_string[i] == '(')
                {
                    Array.Resize(ref stack, stack.Length + 1);
                    stack[stack.Length - 1] = input_string[i].ToString();
                }
                if (input_string[i] == ')')
                {
                    int k_t = stack.Length - 1;
                    while (stack[k_t] != "(")
                        k_t--;
                    int j;
                    for (j = k_t+1; j < stack.Length; j++)
                    {
                        Array.Resize(ref output_string, output_string.Length + 1);
                        output_string[output_string.Length - 1] = stack[j];
                    }
                    Array.Resize(ref stack,stack.Length-j);
                }
                if (input_string[i] == '^')
                {
                    Array.Resize(ref stack, stack.Length + 1);
                    stack[stack.Length - 1] = input_string[i].ToString();
                }
            }
 
            Array.Resize(ref output_string, output_string.Length + stack.Length);
            Array.Reverse(stack);
            for (int i = output_string.Length - stack.Length; i < output_string.Length;i++)
                output_string[i] = stack[k++];
            string t="";
            for (int i = 0; i < output_string.Length; i++)
                if (i != output_string.Length-1)
                    t += output_string[i] + " ";
                else
                    t += output_string[i];
            return t;
        }
 
        public double Solution(string OPZ_String)
        {
            string[] mas = OPZ_String.Split(' ');
            string temp_string;
            for(int i=0;i<mas.Length;i++)
                switch (mas[i])
                { 
                    case "+":
                        temp_string = (double.Parse(mas[i-2]) + double.Parse(mas[i-1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] +"+"+ mas[i - 1]+"="+temp_string+"\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas,mas.Length-2);
                        i -= 2;
                        break;
                    case "-":
                        temp_string = (double.Parse(mas[i - 2]) - double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "-" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                    case "*":
                        temp_string = (double.Parse(mas[i - 2]) * double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "*" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2]=temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        
                        i -= 2;
                        break;
                    case "/":
                        temp_string = (double.Parse(mas[i - 2]) / double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "/" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                    case "^":
                        temp_string = (Math.Pow(double.Parse(mas[i - 2]),double.Parse(mas[i - 1]))).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "^" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                }
            return double.Parse(mas[0]);
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            double result = Solution(Create_OPZ(textBox1.Text));
            this.Text ="Ответ: "+ result.ToString();            
        }
3
 Аватар для YoungBoy
53 / 53 / 2
Регистрация: 19.04.2011
Сообщений: 294
22.04.2011, 00:53
Если бы добавил коменты было бы вообще зашибись
0
0 / 0 / 0
Регистрация: 21.03.2011
Сообщений: 9
22.04.2011, 01:13
Поддерживаю,если бы хоть немного обьяснений было...очень нужно разобраться, да и интерессно очень
0
 Аватар для acrilige
26 / 26 / 7
Регистрация: 03.03.2011
Сообщений: 35
22.04.2011, 04:46
zelen, код у Вас получился каким-то сложным и не очень читабельным

Сделал так, постарался поподробнее закомментировать.
Класс ReversePN, и его статические методы.
Работает только с цифрами и стандартными операциями, но добавить поддержку всего остального не сложно

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using System;
using System.Collections.Generic;
 
namespace PolishNotation
{
    class ReversePN
    {
        /// <summary>
        /// Преобразует обычное математическое выр-е в обратную польскую запись
        /// </summary>
        /// <param name="initialString"> Начальное выражение </param>
        /// <returns> Обратная польская запись выражения </returns>
        public static string ToRPN(string initialString)
        {
            // В стеке будут содержаться операции из выражения
            Stack<char> operationsStack = new Stack<char>();
 
            char lastOperation;
 
            // Результирующая строка
            string result = string.Empty;
            // Удаляем из входной строки лишние пробелы
            initialString = initialString.Replace(" ", "");
 
            for (int i = 0; i < initialString.Length; i++)
            {
                // Если текущий символ - число, добавляем его к результирующей строке
                //
                if (Char.IsDigit(initialString[i]))
                {
                    result += initialString[i];
                    continue;
                }
 
                // Если текущий символ - операция (+, -, *, /)
                //
                if (IsOperation(initialString[i]))
                {
                    // Если это не первая операция в выражении,
                    // то нам необходимо будет сравнить ее
                    // с последней операцией, хранящейся в стеке.
                    // Для этого сохраняем ее в переменной lastOperation
                    //
                    if (!(operationsStack.Count == 0))
                        lastOperation = operationsStack.Peek();
 
                    // Иначе (если это первая операция), кладем ее в стек,
                    // и переходим к следующему символу
                    else
                    {
                        operationsStack.Push(initialString[i]);
                        continue;
                    }
 
                    // Если приоритет текущей операции больше приоритета
                    // последней, хранящейся в стеке, то кладем ее в стек
                    //
                    if (GetOperationPriority(lastOperation) < GetOperationPriority(initialString[i]))
                    {
                        operationsStack.Push(initialString[i]);
                        continue;
                    }
 
                    // иначе, выталкиваем последнюю операцию,
                    // а текущую сохраняем в стек
                    else
                    {
                        result += operationsStack.Pop();
                        operationsStack.Push(initialString[i]);
                        continue;
                    }
                }
 
                // Если текущий символ - '(', кладем его в стек
                if (initialString[i].Equals('('))
                {
                    operationsStack.Push(initialString[i]);
                    continue;
                }
 
                // Если текущий символ - ')', то выталкиваем из стека
                // все операции в результирующую строку, пока не встретим знак '('.
                // Его в строку не закидываем.
                if (initialString[i].Equals(')'))
                {
                    while (operationsStack.Peek() != '(')
                    {
                        result += operationsStack.Pop();
                    }
                    operationsStack.Pop();
                }
            }
 
            // После проверки всей строки, выталкиваем из стека оставшиеся операции
            while (!(operationsStack.Count == 0))
            {
                result += operationsStack.Pop();
            }
 
            // Возвращаем результат
            return result;
        }
 
        /// <summary>
        /// Вычисляет результат выражения, записанного в обратной польской нотации
        /// </summary>
        /// <param name="rpnString"> Обратная польская запись выражения </param>
        /// <returns> Результат выражения </returns>
        public static int CalculateRPN(string rpnString)
        {
            // В стеке будут храниться цифры из ОПН
            Stack<int> numbersStack = new Stack<int>();
 
            int op1, op2;
 
            for (int i = 0; i < rpnString.Length; i++)
            {
                // Если символ - цифра, помещаем его в стек,
                if (Char.IsDigit(rpnString[i]))
                    numbersStack.Push(int.Parse(rpnString[i].ToString()));
 
                // иначе (символ - операция), выполняем эту операцию
                // для двух последних значений, хранящихся в стеке.
                // Результат помещаем в стек
                else
                {
                    op2 = numbersStack.Pop();
                    op1 = numbersStack.Pop();
                    numbersStack.Push(ApplyOperation(rpnString[i], op1, op2));
                }
            }
 
            // Возвращаем результат
            return numbersStack.Pop();
        }
 
        /// <summary>
        /// Проверяет, является ли символ математической операцией
        /// </summary>
        /// <param name="c"> Символ для проверки</param>
        /// <returns> true, если символ - операция, иначе false</returns>
        private static bool IsOperation(char c)
        {
            if (c == '+' ||
                c == '-' ||
                c == '*' ||
                c == '/')
                return true;
            else
                return false;
        }
 
        /// <summary>
        /// Определяет приоритет операции
        /// </summary>
        /// <param name="c"> Символ операции </param>
        /// <returns> Ее приоритет </returns>
        private static int GetOperationPriority(char c)
        {
            switch (c)
            {
                case '+': return 1;
                case '-': return 1;
                case '*': return 2;
                case '/': return 2;
                default: return 0;
            }
        }
 
        /// <summary>
        /// Выполняет матем. операцию над двумя числами
        /// </summary>
        /// <param name="operation"> Символ операции </param>
        /// <param name="op1"> Первый операнд </param>
        /// <param name="op2"> Второй операнд </param>
        /// <returns> Результат операции </returns>
        private static int ApplyOperation(char operation, int op1, int op2)
        {
            switch (operation)
            {
                case '+': return (op1 + op2);
                case '-': return (op1 - op2);
                case '*': return (op1 * op2);
                case '/': return (op1 / op2);
                default: return 0;
            }
        }
    }
}
Ну и небольшой винформс для теста:

C#
1
2
3
4
5
6
private void calculateButton_Click(object sender, EventArgs e)
{
     string result = ReversePN.ToRPN(textBox.Text);
     label1.Text = "RPN Expression: " + result;
     label2.Text = "Answer: " + ReversePN.CalculateRPN(result);
}
5
389 / 304 / 67
Регистрация: 10.07.2010
Сообщений: 802
22.04.2011, 11:30
коменты выложу когда приду с универа.
0
 Аватар для exe-dealer
308 / 161 / 11
Регистрация: 07.06.2009
Сообщений: 538
22.04.2011, 11:42
http://www.codeproject.com/KB/... arser.aspx
0
389 / 304 / 67
Регистрация: 10.07.2010
Сообщений: 802
22.04.2011, 20:34
Лучший ответ Сообщение было отмечено как решение

Решение

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
        public string Create_OPZ(string input_string)
        { 
            string[] output_string=new string[0];//выходная строка(массив)(так она называется на википедии)
            string[] stack=new string[0];//стек
            
            int k = 0;
            for (int i = 0; i < input_string.Length; i++)
            {
                string temp = "";//как бы это было не удивительно, но переменная для хранения числа
                //проверка на отрицательное число: зсли знак "-" в начале строки или перед знаком "-" нет числа
                if (input_string[i] == '-' && ((i > 0 && !Char.IsDigit(input_string[i - 1])) || i == 0))
                {
                    i++;
                    temp += "-";//в переменную для чисел добавляется знак "-"
                }
                if (Char.IsDigit(input_string[i]))
                {                    
                    //найдено число и в переменную temp записываются все цифры числа, тк число может состоять не только из одной цифры
                    while (i < input_string.Length&&Char.IsDigit(input_string[i]))
                        temp += input_string[i++].ToString();
                    i--;
                    Array.Resize(ref output_string, output_string.Length + 1);//массив выходной строки динамически увеличиваем на единицу
                    output_string[output_string.Length - 1] = temp;//добавляем число в текущий элемент выходной строки
                }
                if (input_string[i] == '+' || input_string[i] == '-')
                {
                m://т.к + и - имеют самый низкий приоритет, то при записывании этих операндов в стек 
                    //все остальные операции из стека должны переместится в выходную строку(исключение скобка) 
                    if (stack.Length != 0) //если стек еще не пуст
                    {
                        if (stack[stack.Length - 1] == "(")//если последний элемент стека открывающаяся скобка 
                        {
                            Array.Resize(ref stack, stack.Length + 1);
                            stack[stack.Length - 1] = input_string[i].ToString();//то в стек добавляется операция сложения или отрицания 
                        }
                        else //иначе
                        {
                            Array.Resize(ref output_string, output_string.Length + 1);
                            output_string[output_string.Length - 1] = stack[stack.Length - 1];//в выходную строку добавляется последняя операция из стека
                            Array.Resize(ref stack, stack.Length - 1);//у стека удаляется последний элемент
                            goto m;//возврат на проверку находится ли на вершине стека еще какая либо операция
                        }
                        stack[stack.Length - 1] = input_string[i].ToString();//на вершину стека помещается операция + или -
                    }
                    else
                    {
                        Array.Resize(ref stack, stack.Length + 1);
                        stack[stack.Length - 1] = input_string[i].ToString();//если стек не пуст то в стек добавляется операция сложения или отрицания
                    }
                }
                if (input_string[i] == '*' || input_string[i] == '/')
                {
 
                    if (stack.Length != 0)//если стек еще не пуст
                    {
 
                        if (stack[stack.Length - 1] != "*" && stack[stack.Length - 1] != "/")//если на вершине стека не располагается * или /
                        {
                            Array.Resize(ref stack, stack.Length + 1);
                            stack[stack.Length - 1] = input_string[i].ToString();
                        }
                        else  //если на вершине стека располагается * или /
                        {//то т.к приоритеты операций одинаковые... 
                            Array.Resize(ref output_string, output_string.Length + 1);
                            output_string[output_string.Length - 1] = stack[stack.Length - 1];//...элемент с вершины стека передается в выходную строку(массив)
                            stack[stack.Length - 1] = input_string[i].ToString();//на вершину стека становится текщая операция умножения или деления
                            
                        }
                        
                    }
                    else
                    {
                        Array.Resize(ref stack, stack.Length + 1);
                        stack[stack.Length - 1] = input_string[i].ToString();//если стек не пуст то в стек добавляется операция умножения или деления
                    }
                }
                if (input_string[i] == '(')
                {//найдена открывающаяся скобка которая автоматически добавляется в стек
                    Array.Resize(ref stack, stack.Length + 1);
                    stack[stack.Length - 1] = input_string[i].ToString();
                }
                if (input_string[i] == ')')
                {//найдена закрывающаяся скобка
                    int k_t = stack.Length - 1;
                    while (stack[k_t] != "(")//некий цикл который начиная с конца стека перемещается влево в поисках открывающиейся скобки
                        k_t--;//после цикла здесь хранится индекс открывающейся скобки
                    int j;
                    for (j = k_t+1; j < stack.Length; j++)//все операции которые хранились в стеке после "(" переносятся в выходную строку
                    {
                        Array.Resize(ref output_string, output_string.Length + 1);
                        output_string[output_string.Length - 1] = stack[j];
                    }
                    Array.Resize(ref stack,stack.Length-j);//стек уменьшается на количество переданных операций
                }
                if (input_string[i] == '^')//т.к у возведения в степень самый большой приоритет, его автоматически добавляют в выходную строку
                {
                    Array.Resize(ref stack, stack.Length + 1);
                    stack[stack.Length - 1] = input_string[i].ToString();
                }
            }
            //всю ВХодную строку проверили теперь в стеке и в ВЫХодной строке содержатся некоторые данные
            //объединяем выходную строку со стеком
            Array.Resize(ref output_string, output_string.Length + stack.Length);
            Array.Reverse(stack);//это просто что бы не парится и не создавать цкл который будет идти задом на перед
            //т.к иначе есть свои нюансы в которые я вдаваться не хочу
            for (int i = output_string.Length - stack.Length; i < output_string.Length;i++)
                output_string[i] = stack[k++];
            string t="";//сформировали из выходной строки(массива) строку
            for (int i = 0; i < output_string.Length; i++)
                if (i != output_string.Length-1)
                    t += output_string[i] + " ";
                else
                    t += output_string[i];
            return t;//передали полученную строку
        }
 
        public double Solution(string OPZ_String)
        {
            string[] mas = OPZ_String.Split(' ');//нарезаем строку в виде Обратной польской записи в массив элементов
            string temp_string;
            for(int i=0;i<mas.Length;i++)
                switch (mas[i])
                {
                    case "+"://если найдена операция сложения
                        temp_string = (double.Parse(mas[i - 2]) + double.Parse(mas[i - 1])).ToString();//выполняем сложение и переводим ее в строку
                        richTextBox1.AppendText(mas[i - 2] +"+"+ mas[i - 1]+"="+temp_string+"\n");
                        mas[i - 2] = temp_string;//на место 1-ого операнда записывается результат (как если бы a=a+b)
                        for (int j = i - 1; j < mas.Length - 2; j++)//удаляем из массива второй операнд и знак арифм действия
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas,mas.Length-2);//обрезаем массив элементов на 2 удаленнх элемента
                        i -= 2;
                        break;
                    case "-"://далее все аналогично
                        temp_string = (double.Parse(mas[i - 2]) - double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "-" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                    case "*":
                        temp_string = (double.Parse(mas[i - 2]) * double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "*" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2]=temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        
                        i -= 2;
                        break;
                    case "/":
                        temp_string = (double.Parse(mas[i - 2]) / double.Parse(mas[i - 1])).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "/" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                    case "^":
                        temp_string = (Math.Pow(double.Parse(mas[i - 2]),double.Parse(mas[i - 1]))).ToString();
                        richTextBox1.AppendText(mas[i - 2] + "^" + mas[i - 1] + "=" + temp_string + "\n");
                        mas[i - 2] = temp_string;
                        for (int j = i - 1; j < mas.Length - 2; j++)
                            mas[j] = mas[j + 2];
                        Array.Resize(ref mas, mas.Length - 2);
                        i -= 2;
                        break;
                }
            return double.Parse(mas[0]);
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            double result = Solution(Create_OPZ(textBox1.Text));
            this.Text ="Ответ: "+ result.ToString();            
        }
Добавлено через 1 час 43 минуты
найдены и устранены 2-е ошибки в операции со скобками (с закрывающейся скобкой)
C#
1
2
3
4
5
6
7
8
        int kol=0;
        for (int j = stack.Length-1; j >= k_t + 1; j--)//все операции которые хранились в стеке после "(" переносятся в выходную строку
        {
              kol++;
              Array.Resize(ref output_string, output_string.Length + 1);
              output_string[output_string.Length - 1] = stack[j];
         }
         Array.Resize(ref stack,stack.Length-(kol+1));//стек уменьшается на количество переданных операций
1
0 / 0 / 0
Регистрация: 21.03.2011
Сообщений: 9
22.04.2011, 23:07
Спасибо большое, очень помог
0
41 / 41 / 10
Регистрация: 22.05.2009
Сообщений: 492
24.12.2012, 18:48
Уже обрадовался что нашел ОПЗ=)
Но вариант acrilige не дружит с отрицательными числами
А варант zelen не дружит с вещественными числами

Есть варианты для исправления?))
0
0 / 0 / 0
Регистрация: 16.05.2016
Сообщений: 8
20.05.2016, 04:59
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
class RPN
        {
            
            static public double Calculate(string input)//"входной" метод класса
            {
                
                string output = GetExpression(input);//преобразование выражения в постфиксную запись
                double result = Counting(output);//решение выражения
                return result;
                
            }
            
            
 
            static public 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 (input[i] == '-' && ((i>0&&!Char.IsDigit(input[i - 1]))||i==0))
                    {
                        i++;
                        output += "-";//в переменную для чисел добавляется знак "-"    
                    }
                 
                    
                    //Если символ - цифра, то считываем все число
                    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() + " ";
 
                    return output; //Возвращаем выражение в постфиксной записи
               
                }
            
            static private double Counting(string output)//метод решения OPN
            {
                string result;
 
                string[] mas = output.Split(' ');
                
                for (int i = 0; i < mas.Length; i++)
                    
                    switch (mas[i])
                    {
                        case "+"://если найдена операция сложения
                            result = (double.Parse(mas[i - 2]) + double.Parse(mas[i - 1])).ToString();//выполняем сложение и переводим ее в строку
                            mas[i - 2] = result;//на место 1-ого операнда записывается результат (как если бы a=a+b)
                            for (int j = i - 1; j < mas.Length - 2; j++)//удаляем из массива второй операнд и знак арифм действия
                                mas[j] = mas[j + 2];
                            Array.Resize(ref mas, mas.Length - 2);//обрезаем массив элементов на 2 удаленнх элемента
                            i -= 2;
                            break;
 
 
                        case "-"://далее все аналогично
                            result = (double.Parse(mas[i - 2]) - double.Parse(mas[i - 1])).ToString();
                            mas[i - 2] = result;
                            for (int j = i - 1; j < mas.Length - 2; j++)
                                mas[j] = mas[j + 2];
                            Array.Resize(ref mas, mas.Length - 2);
                            i -= 2;
                            break;
 
                        case "*":
                            result = (double.Parse(mas[i - 2]) * double.Parse(mas[i - 1])).ToString();
                            mas[i - 2] = result;
                            for (int j = i - 1; j < mas.Length - 2; j++)
                                mas[j] = mas[j + 2];
                            Array.Resize(ref mas, mas.Length - 2);
                            i -= 2;
                            break;
 
                        case "/":
                            result = (double.Parse(mas[i - 2]) / double.Parse(mas[i - 1])).ToString();
                            mas[i - 2] = result;
                            for (int j = i - 1; j < mas.Length - 2; j++)
                                mas[j] = mas[j + 2];
                            Array.Resize(ref mas, mas.Length - 2);
                            i -= 2;
                            break;
 
 
                        case "^":
                            result = (Math.Pow(double.Parse(mas[i - 2]), double.Parse(mas[i - 1]))).ToString();
                            mas[i - 2] = result;
                            for (int j = i - 1; j < mas.Length - 2; j++)
                                mas[j] = mas[j + 2];
                            Array.Resize(ref mas, mas.Length - 2);
                            i -= 2;
                            break;
 
 
                    }
                return double.Parse(mas[0]);
            }
                    
            
 
            
 
 
            //Метод возвращает приоритет оператора
            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;
                }
            }
            //Метод возвращает true, если проверяемый символ - оператор
            static private bool IsOperator(char с)
            {
                if (("+-/*^()".IndexOf(с) != -1))
                    return true;
                return false;
            }
 
            //Метод возвращает true, если проверяемый символ - разделитель ("пробел" или "равно")
            static private bool IsDelimeter(char c)
            {
                if ((" =".IndexOf(c) != -1))
                    return true;
                return false;
            }
        }
Добавлено через 6 минут
Если подскажете, как исправить ошибку,буду благодарен.
Дело в том, что если пользователь вводит выражение "-(9+6)", программа считает неправильно. В идеале нужно в переменную для чисел занести 0, чтобы из него вычитался результат в скобках и результат был отрицательным.
Вот код, 0 заносится как нужно, а вот знак "-", что перед скобками, как занести в стек?
C#
1
2
3
4
5
 if (input[i] == '-' && ((i > 0 && !Char.IsDigit(input[i - 1]) && input[i + 1] == '('))||i==0)
                    {
                        i++;
                       output += "0";
                    }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.05.2016, 04:59
Помогаю со студенческими работами здесь

Как использовать обратную польскую запись для решения дробно-рациональных уравнений
Как использовать обратную польскую запись для решения дробно-рациональных уравнений? строка ввода в textBox

Преобразовать строку в обратную польскую запись.
Собственно как это реализовать. Например входная строка &quot;AvB&quot; (где A и B заглавные симвволы) должен получить &quot;B A v&quot; А этот...

Преобразование выражения в польскую запись
Помогите, пожалуйста, преобразовать выражение (d + g + h) / c - t * j в польскую запись.

Калькулятор, понимающий обратную польскую нотацию.Ошибка
задача была, написать калькулятор, который понимает обратную польскую запись. по Логике, написать-написал. Но вот результат всегда выводит...

Строку в обратную польскую запись
Подскажите, как представить выражение из строки в обратную польскую запись и потом посчитать? Наверное есть уже готовые алгоритмы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru