В настоящее время я перехожу с Java на Python и взял на себя задачу создания калькулятора, который может выполнять символические операции над математическими выражениями с инфиксной нотацией ( без использования пользовательских модулей, таких как Sympy ).,В настоящее время он построен для приема строк, разделенных пробелами, и может выполнять только операторы (,), +, -, * и /.К сожалению, я не могу понять базовый алгоритм для упрощения символьных выражений.
Например, учитывая строку '2 * ((9/6) + 6 * x)', моя программа должна выполнитьследующие шаги:
- 2 * (1,5 + 6 * x)
- 3 + 12 * x
Но я не могу заставить программуигнорировать x при распределении 2. Кроме того, как я могу обработать 'x * 6 / x', чтобы он возвращал '6' после упрощения?
РЕДАКТИРОВАТЬ: Чтобы уточнить, с помощью "символическое «Я имел в виду, что во время выполнения оставшихся вычислений в выводе будут присутствовать буквы типа« А »и« f ».
РЕДАКТИРОВАТЬ 2: Я (в основном) закончил код.Я публикую его здесь, если кто-нибудь в будущем наткнется на этот пост, или если кому-то из вас будет любопытно.
def reduceExpr(useArray):
# Use Python's native eval() to compute if no letters are detected.
if (not hasLetters(useArray)):
return [calculate(useArray)] # Different from eval() because it returns string version of result
# Base case. Returns useArray if the list size is 1 (i.e., it contains one string).
if (len(useArray) == 1):
return useArray
# Base case. Returns the space-joined elements of useArray as a list with one string.
if (len(useArray) == 3):
return [' '.join(useArray)]
# Checks to see if parentheses are present in the expression & sets.
# Counts number of parentheses & keeps track of first ( found.
parentheses = 0
leftIdx = -1
# This try/except block is essentially an if/else block. Since useArray.index('(') triggers a KeyError
# if it can't find '(' in useArray, the next line is not carried out, and parentheses is not incremented.
try:
leftIdx = useArray.index('(')
parentheses += 1
except Exception:
pass
# If a KeyError was returned, leftIdx = -1 and rightIdx = parentheses = 0.
rightIdx = leftIdx + 1
while (parentheses > 0):
if (useArray[rightIdx] == '('):
parentheses += 1
elif (useArray[rightIdx] == ')'):
parentheses -= 1
rightIdx += 1
# Provided parentheses pair isn't empty, runs contents through again; else, removes the parentheses
if (leftIdx > -1 and rightIdx - leftIdx > 2):
return reduceExpr(useArray[:leftIdx] + [' '.join(['(',reduceExpr(useArray[leftIdx+1:rightIdx-1])[0],')'])] + useArray[rightIdx:])
elif (leftIdx > -1):
return reduceExpr(useArray[:leftIdx] + useArray[rightIdx:])
# If operator is + or -, hold the first two elements and process the rest of the list first
if isAddSub(useArray[1]):
return reduceExpr(useArray[:2] + reduceExpr(useArray[2:]))
# Else, if operator is * or /, process the first 3 elements first, then the rest of the list
elif isMultDiv(useArray[1]):
return reduceExpr(reduceExpr(useArray[:3]) + useArray[3:])
# Just placed this so the compiler wouldn't complain that the function had no return (since this was called by yet another function).
return None