2016-12-02 11 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を返すので、計算ステップを印刷されますこれは私が最初 NUMをしたという事実に頼っていること

>>> 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 

注:ステップバイ表現式はverbose_numberです。アプローチの改良は、解析する文字列式のための便利なルーチンを書くことです:これは、それによってすべての手順がされることを保証し、verbose_numberコンストラクタ呼び出しに文字列内のすべての数値リテラルを回すことによって動作

import re 
def print_steps(expression): 
    return eval(re.sub(r'([0-9\.]+([eE]-?[0-9]+)?)', r'verbose_number(\1)', expression)) 

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')) 

きれいにフォーマットした場合、出力は次のようになります。ジェズのanswerに触発さ

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) 
    ) 
) 
) 

私はいくつかの線形ステップにダンプを変換するために、次の解決策を考え出した:

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)

関連する問題