2016-12-02 55 views
0

我想知道是否有方法打印每個步驟,考慮python遵循PEMDAS 。我可以在打印每一步的過程中解決這個問題,而無需構建自己的庫嗎?將數學表達式分解爲步驟

print_steps('(3+7-2)*4/(3+32)') 

括號,指數,乘法和除法,及加法和減法

+0

此代碼是類型錯誤。 – ForceBru

回答

2

「庫」可以是相當輕巧:

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 
1

不。即使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 
2

你可以使用ast.parseast.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')爲您提供: astviewer for 3+7-2)*4/(3+32)