解析数学表达式的程序输入字符串

时间:2016-12-05 02:36:42

标签: python string python-3.x parsing math

我正在尝试编写一个像@property (nonatomic,weak) id<ProtocolDelegate> protocol_delegate; 这样的数学表达式求解器。 我目前的障碍是弄清楚哪些开启和关闭支架是对应的。

例如,我如何确定worlfram alpha中哪些括号匹配。该程序将单独解决这些部分中的每一部分,并在这样做时用答案替换原始部分。

因此,举例来说,该程序试图在((1 * 3) / (4 / 2))中尝试解决的第一部分将是((1 * 3) / (4 / 2)),因此它会用产品3替换该部分,(1 * 3)会现在是((1 * 3) / (4 / 2))

我目前的代码(如果有用) - http://pastebin.com/Xpayzbff,处理配对的功能是(3 / (4 / 2))

谢谢!

2 个答案:

答案 0 :(得分:0)

我不会为你编写代码,因为那会破坏这一点,但你可能想要的是Shunting-yard algorithm。它从中缀(人类通常代表一系列操作,操作符操作数中)转换为后缀(计算机很容易评估,操作符之后)操作数。)。

以下是在python中为布尔登录执行此操作的人:https://msoulier.wordpress.com/2009/08/01/dijkstras-shunting-yard-algorithm-in-python/

您还可以尝试将语句直接解析为AST,然后您可以对其进行操作。

另外请务必查看tokenizer module for python。

答案 1 :(得分:0)

您可以使用Shunting-Yard算法。但是,涉及算法的完整实现。这是一个更简单,有些天真的版本,可以使您基本了解https://gist.github.com/tiabas/339f5c06f541c176a02c02cc3113d6f7

# Simple Shunting-Yard solution
#
# Given a math expression, parse and evaluate
# the expression
#
# E.g '2+1' => 3, 8/2*4+1 => 17, 2+(1*2) = 4, ((2+4)/2*7) => 21
# 
def parse_math_expression(exp):
    PRECENDENCE = {
        ')': 3,
        '(': 3,
        '*': 1,
        '/': 1,
        '+': 0,
        '-': 0,
    }
    output = []
    operators = []
    for ch in exp:
        # Handle nested expressions
        if ch == ')':
            opr = operators.pop(0)
            while opr != '(':
                output.append(opr)
                opr = operators.pop(0)
        elif ch.isdigit():
            output.append(ch)
        else:
            # Handle operator prescendence
            top_op = None
            if len(operators) and operators[0]:
                top_op = operators[0]
            # Check if top operator has greater prcendencethan current char
            if top_op in ['*', '/'] and PRECENDENCE[top_op] > PRECENDENCE[ch]:
                output.append(top_op)
                operators.pop(0)
            # Push operator onto queues
            operators.insert(0, ch)
    # Handle any leftover operators
    while len(operators):
        output.append(operators.pop(0))
    return output

test1 = "(2+1)"
assert parse_math_expression(test1) == ['2', '1', '+']
test2 = "((2+4)/(2*7))"
assert parse_math_expression(test2) == ['2', '4', '+', '2', '7', '*', '/']
test3 = "(3*2)+(4/2)"
assert parse_math_expression(test3) == ['3', '2', '*','4', '2', '/','+']

def eval_parsed_expression(exp):
    OPRS = {
        '+': lambda a, b: a + b,
        '-': lambda a, b: a - b,
        '*': lambda a, b: a * b,
        '/': lambda a, b: a / b
    }
    tmp = []
    while len(exp) > 1:
        k = exp.pop(0)
        while not k in ['*', '-', '+', '/']:
            tmp.insert(0, k)
            k = exp.pop(0)
        o = k
        b = tmp.pop(0)
        a = tmp.pop(0)
        r = OPRS[o](int(a), int(b))
        exp.insert(0, r)
    return exp[0]

test4 = ['2', '1', '+'] # (2+1*2)
assert eval_parsed_expression(test4) == 3
test5 = ['2', '1', '2', '*', '+'] # (2+1*2)
assert eval_parsed_expression(test5) == 4
test6 = ['3', '2', '*','4', '2', '/','+'] # (3*2)+(4/2)
assert eval_parsed_expression(test6) == 8