我有一项任务,我需要使用Python将一种语言(MATLAB)的方程转换为另一种语言(C ++)。除了动力操作外,一切都很简单。方程式由Python字符串表示。
例如,我想转换
Eq = ((a+b)^2 + (c+d)^(1/2)) * e
要,
Eq = (pow((a+b),2) + pow(c+d, 1/2)) * e
我尝试了正则表达式,但由于嵌套括号,它似乎不起作用。有没有好办法呢?
答案 0 :(得分:2)
解决此问题的最佳方法是使用Python的抽象语法树。我们可以使用ast
模块来实现。
import ast, _ast
ops = {_ast.Mult: "*", _ast.Add: "+", _ast.BitXor: "pow", _ast.Div: "/"}
def rec(n):
if isinstance(n, _ast.Expr):
return rec(n.value)
elif isinstance(n, _ast.BinOp):
if isinstance(n.op, _ast.BitXor):
return "{}({}, {})".format(ops[type(n.op)], rec(n.left),rec(n.right))
else:
return "({} {} {})".format(rec(n.left), ops[type(n.op)],rec(n.right))
elif isinstance(n, _ast.Name):
return n.id
elif isinstance(n, _ast.Num):
return n.n
print rec(ast.parse("(((a+b)^2) + ((c+d)^(1/2))) * e").body[0])
# ((pow((a + b), 2) + pow((c + d), (1 / 2))) * e)
注意:由于^
表示Python中的二进制异或操作,因此需要用一个额外的括号括起该表达式,就像我在示例中所示。
首先,我们检查它是否是表达式,然后我们处理它的值。如果它是二进制操作,我们检查它是否为Bitwise XOR,在这种情况下我们以不同的格式返回结果,否则我们返回像left op right
这样的结果。如果当前项看起来像名称,那么我们会返回其id
,如果是数字,我们会返回属性n
。
答案 1 :(得分:1)
您可以按照以下方式执行此操作。注意:这仍然是一种非常原始的方法,我要小心依赖它100%:
import re
s = "Eq = ((a+b)^2 + (c+d)^(1/2)) * e"
>>> print re.sub(r'\(([^()\s]*)\)\^\(?([^()\s]*)\)?', 'pow(\\1,\\2)', s)
Eq = (pow(a+b,2) + pow(c+d,1/2)) * e
答案 2 :(得分:0)
我认为我使用简单的tokeniser和解析器而不是正则表达式来做到这一点。它不是that hard编写的,并且比基于正则表达式的解析器更强大和可读。