W tej chwili przechodzę z Java do Pythona i podjęłam się zadania stworzenia kalkulatora, który może wykonywać operacje symboliczne na wyrażeń matematycznych opatrzonych inffikacją (bez używania modułów niestandardowych, takich jak Sympy). Obecnie jest zbudowany, aby akceptować łańcuchy, które są rozdzielane spacjami i może wykonywać tylko operatory (,), +, -, * i /. Niestety, nie mogę znaleźć podstawowego algorytmu do uproszczenia wyrażeń symbolicznych.Czy mogę napisać funkcję wykonującą obliczenia symboliczne w Pythonie 2.7?
Na przykład, biorąc pod uwagę ciąg '2 * ((9/6) + 6 * x)' my programu należy przeprowadzić następujące czynności:
- 2 * (1,5 + 6 * x)
- 3 + 12 * x
Ale nie mogę uzyskać program do ignorowania x podczas rozprowadzania 2.
Ponadto, w jaki sposób można obsłużyć 'x * 6/x' tak zwraca ' 6 'po uproszczeniu?
EDYCJA: Aby wyjaśnić, przez "symboliczne" miałem na myśli, że pozostawi litery takie jak "A" i "f" na wyjściu podczas wykonywania pozostałych obliczeń.
EDYCJA 2: I (w większości) zakończyłem kod. Zamieszczam go tutaj, jeśli ktoś natknie się na ten post w przyszłości, lub jeśli ktoś z was był ciekawy.
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
Chyba zaczynasz zobaczyć cnotę Sympy :-) Myślę, że patrząc na budowę pełnoprawnym zejście rekurencyjne dla parsera wyrażeń arytmetycznych, a następnie manipulacji drzewa danych rozwiązania dla X. – wberry
TAK !!! Możesz;) – Drakosha
@ li.davidm Wciąż jest na etapie logiki. Nie mogę wymyślić, jak wprowadzić w życie po pierwszym potknięciu. – Edwin