Вы можете выполнить поиск по запросу "алгоритм маневровой станции". Это довольно фундаментальный алгоритм вычисления выражений, и он использует два стека (хотя один из них называется «очередью вывода»).
По сути, вы фильтруете номера от операторов. Числа отправляются в выходной стек, операторы — в «удерживающий» стек. Когда появляется оператор с более низким приоритетом, чем в стеке хранения, вы перемещаете содержимое стека хранения в выходной стек до тех пор, пока либо стек хранения не станет пустым, либо элемент в стеке хранения не будет иметь более низкий приоритет, чем оператор ввода. .
Приоритет
Помните, что a + b * c - d
оценивается как (a + (b*c)) - d
. Помните также, что возведение в степень имеет более высокий приоритет, чем умножение, поэтому a * b ^ c
будет a * (b ^ c)
.
ИЗМЕНИТЬ:
Вот код, который не работает. Я не знаю, что такое ваши операторы '>' и '‹'. Судя по всему (10 ‹ 2) должно быть 2, из третьего выражения?
Я просто реализовал их как логические значения в стиле C (1 для истины, 0 для ложных).
Там куча лишнего кода, потому что только одна функция. Не стесняйтесь очистить это. Он модифицирует алгоритм Shunting Yard для выполнения расчетов RPN на лету. Я оставил кучу операторов печати, которые иллюстрируют содержимое списков, которые я использую в качестве стеков. Не стесняйтесь делать правильную работу со своими классами стека. В моей версии pop()
это pop, а append()
push.
tests = [
'2 ^ ( 1 + 3 ^ 2 )',
'( 3 * 5 ) - ( 1 > 2 > 3 < 4 )',
'4 ^ ( 10 < 2 ) / 5 + 100',
]
expected = [
1024,
12,
103,
]
def expr_eval(s):
print("EXPR:", s)
tokens = s.split()
output_stk = []
operator_stk = []
precedence = {
'(': 0,
'+':1, '-':1, '<':1, '>':1,
'*':2, '/':2,
'^':3,
}
for t in tokens:
print("OUT:", output_stk, "OP:", operator_stk)
print("Tok: ",t)
if t.isdigit():
output_stk.append(int(t))
continue
elif t == '(':
operator_stk.append(t)
continue
elif t == ')':
# End of subexpression. Do math until we find opening (
while operator_stk:
op = operator_stk.pop()
if op == '(':
break
b = output_stk.pop()
a = output_stk.pop()
if op == '-': output_stk.append(a - b)
elif op == '+': output_stk.append(a + b)
elif op == '<': output_stk.append(1 if a < b else 0)
elif op == '>': output_stk.append(1 if a > b else 0)
elif op == '*': output_stk.append(a * b)
elif op == '/': output_stk.append(a // b)
elif op == '^': output_stk.append(a ** b)
else:
raise Exception("Unknown operator: %s" % op)
print("OUT:", output_stk, "OP:", operator_stk)
continue
# Not a number - check operator precedence
prec_t = precedence[t]
while operator_stk and prec_t <= precedence[operator_stk[-1]]:
print("OUT:", output_stk, "OP:", operator_stk)
op = operator_stk.pop()
b = output_stk.pop()
a = output_stk.pop() # 'a' went on first!
if op == '-': output_stk.append(a - b)
elif op == '+': output_stk.append(a + b)
elif op == '<': output_stk.append(1 if a < b else 0)
elif op == '>': output_stk.append(1 if a > b else 0)
elif op == '*': output_stk.append(a * b)
elif op == '/': output_stk.append(a // b)
elif op == '^': output_stk.append(a ** b)
else:
raise Exception("Unknown operator: %s" % op)
operator_stk.append(t)
print("OUT:", output_stk, "OP:", operator_stk)
while operator_stk:
op = operator_stk.pop()
if op == '(':
raise Exception('Mismatched opening parenthesis!')
b = output_stk.pop()
a = output_stk.pop() # 'a' went on first!
if op == '-': output_stk.append(a - b)
elif op == '+': output_stk.append(a + b)
elif op == '<': output_stk.append(1 if a < b else 0)
elif op == '>': output_stk.append(1 if a > b else 0)
elif op == '*': output_stk.append(a * b)
elif op == '/': output_stk.append(a // b)
elif op == '^': output_stk.append(a ** b)
else:
raise Exception("Unknown operator: %s" % op)
print("OUT:", output_stk, "OP:", operator_stk)
return output_stk.pop()
for i in range(len(tests)):
r = expr_eval(tests[i])
if r == expected[i]:
print("PASS: %d = %s" % (r, tests[i]))
else:
print("FAIL: %d != %d = %s" % (r, expected[i], tests[i]))
person
aghast
schedule
02.02.2017