我想知道是否有方法打印每個步驟,考慮python遵循PEMDAS 。我可以在打印每一步的過程中解決這個問題,而無需構建自己的庫嗎?將數學表達式分解爲步驟
print_steps('(3+7-2)*4/(3+32)')
括號,指數,乘法和除法,及加法和減法
我想知道是否有方法打印每個步驟,考慮python遵循PEMDAS 。我可以在打印每一步的過程中解決這個問題,而無需構建自己的庫嗎?將數學表達式分解爲步驟
print_steps('(3+7-2)*4/(3+32)')
括號,指數,乘法和除法,及加法和減法
「庫」可以是相當輕巧:
class verbose_number:
def __init__(self, value): self.value = value
def operate(self, operator, other):
other = getattr(other, 'value', other)
result = eval('self.value %s other' % operator)
print('%r %s %r = %r' % (self.value, operator, other, result))
return self.__class__(result)
def __add__(self, other): return self.operate('+', other)
def __sub__(self, other): return self.operate('-', other)
def __mul__(self, other): return self.operate('*', other)
def __div__(self, other): return self.operate('/', other)
def __floordiv__(self, other): return self.operate('//', other)
def __truediv__(self, other): return self.operate('/', other)
def __pow__(self, other): return self.operate('**', other)
def __mod__(self, other): return self.operate('%', other)
def __neg__(self): return self.__class__(-self.value)
def __pos__(self): return self.__class__(+self.value)
def __repr__(self): return repr(self.value)
def __int__(self): return int(self.value)
def __float__(self): return float(self.value)
現在涉及verbose_number
實例獲取打印並返回另一個verbose_number
,因此計算打印步驟中,任何的算術計算一步:
>>> from __future__ import division
>>> (verbose_number(3)+7-2)*4/(3+32)
3 + 7 = 10
10 - 2 = 8
8 * 4 = 32
3 + 32 = 35
32/35 = 0.9142857142857143
注意,這依賴於我所做的第一NUM事實在表達式a verbose_number
中。在方法的一個改進是編寫一個方便的日常解析字符串表達式:
import re
def print_steps(expression):
return eval(re.sub(r'([0-9\.]+([eE]-?[0-9]+)?)', r'verbose_number(\1)', expression))
這是通過轉動每數字字符的字符串中爲verbose_number
構造函數的調用,從而確保所有步驟將是verbose無論Python的解析器在表達式中的何處開始。以下是它如何用於評估您的示例:
>>> print_steps('(3+7-2)*4/(3+32)')
3 + 7 = 10
10 - 2 = 8
8 * 4 = 32
3 + 32 = 35
32/35 = 0.9142857142857143
不。即使dis.dis
也不會向您顯示單個步驟,因爲它們在被編譯爲字節碼之前都被簡化爲單個常量。
>>> def f():
... return (3+7-2)*4/(3+32)
...
>>> import dis
>>> dis.dis(f)
2 0 LOAD_CONST 10 (0.9142857142857143)
3 RETURN_VALUE
你可以使用ast.parse
和ast.dump
得到它的把握。
import ast
ast.dump(ast.parse('(3+7-2)*4/(3+32)', mode='eval'))
如果格式化很好,輸出可以是這樣的:
Expression(
body=BinOp(
left=BinOp(
left=BinOp(
left=BinOp(
left=Num(n=3),
op=Add(),
right=Num(n=7)
),
op=Sub(),
right=Num(n=2)
),
op=Mult(),
right=Num(n=4)
),
op=Div(),
right=BinOp(
left=Num(n=3),
op=Add(),
right=Num(n=32)
)
)
)
由傑斯的answer啓發我想出了以下解決轉儲轉化成一些線性步驟:
import operator
Expression = lambda body: body
Num = lambda n: n
USub = lambda : ('-', operator.neg)
Add = lambda : ('+', operator.add)
Sub = lambda : ('-', operator.sub)
Mult = lambda : ('*', operator.mul)
Div = lambda : ('/', operator.truediv)
FloorDiv = lambda : ('//', operator.floordiv)
def UnaryOp(op, operand):
print(op[0], operand)
result = op[1](operand)
print(' =', result)
return result
def BinOp(left, op, right):
result = op[1](left, right)
print(left, op[0], right, '=', result)
return result
eval(ast.dump(ast.parse('(3+7-2)*4/(3+32)', mode='eval')))
它打印:
3 + 7 = 10
10 - 2 = 8
8 * 4 = 32
3 + 32 = 35
32/35 = 0.9142857142857143
astviewer可以給你樹的圖形表示。例如astviewer.main.view(source_code='(3+7-2)*4/(3+32)', mode='eval')
爲您提供:
此代碼是類型錯誤。 – ForceBru