Question

I have a task where I need to convert equations in one language (MATLAB) to another (C++) using Python. Everything is straightforward except the power operation. The equations are represented by Python strings.

For example, I want to convert

Eq = ((a+b)^2 + (c+d)^(1/2)) * e

to,

Eq = (pow((a+b),2) + pow(c+d, 1/2)) * e

I tried regular expression, but it does not seem to work because of nested parenthesis. Is there any good way to do this?

Was it helpful?

Solution

The best way to solve this would be to use Abstract Syntax Tree of Python. We can get that using ast module.

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)

Note: Since ^ means Binary XOR operation in Python, you need to enclose that expression with an extra parenthesis, like I have shown in the example.

First, we check if it is an expression, then we process its value. If it is a binary operation, we check of it is Bitwise XOR, in that case we return the result in a different format, otherwise we return the result like left op right. If the current item looks like a name, then we return its id or if it is a number we return the attribute n.

OTHER TIPS

You can do it as follows. Note: This is still a very primitive approach and I'd be careful about relying on it 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

I think I'd do this with a simple tokeniser and parser rather than regular expressions. It's not that hard to write and will be more robust and readable than a regular expression based parser.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top