我有一个字符串格式的函数f(t,u,v)
;例如't^2 * sint + u*(20 + t) + v*t'
。
我该如何解决这个功能?
我试着这样做:
t = Symbol('t')
u = mu
v = mv
sol = eval(f)
但我收到错误name 'sint' is not defined
答案 0 :(得分:1)
使用eval
不是最好的方法。
SymPy parser具有允许使用t^2
(称为convert_xor
)和sin t
(称为implicit_application
)等内容解析字符串的选项。这是一个例子:
from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_application, convert_xor
transformations = standard_transformations + (implicit_application, convert_xor)
f = parse_expr('t^2 * sin t + u*(20 + t) + v*t', transformations=transformations)
现在f
是t**2*sin(t) + t*v + u*(t + 20)
,您可以正常使用它,例如
solve(f.subs({Symbol('u'): 4}), Symbol('v')) # returns [-t*sin(t) - 4 - 80/t]
您可能希望介绍u, v, t = symbols('u v t')
以便更轻松地访问这些符号。
不幸的是sint
不会被识别为sin(t)
;缺乏空间是致命的。这必须经过预处理,可能使用正则表达式。例如,
import re
s = re.sub(r'\bsin', 'sin ', 't^2 * sint + u*(20 + t) + v*t')
在每次“罪恶”之后留下一个空间(额外的空间不会受到伤害)。
答案 1 :(得分:0)
这相当丑陋,但您可以在评估表达式之前使用正则表达式(稍微)格式化表达式。您可能不得不在下面修改以下代码以满足您的需求。
import re
import textwrap
import math
functionBaseCode = textwrap.dedent("""
def f({variables}):
return {mathExpr}
""")
def generateFunctionFromExpression(expression, variables):
expression = expression.replace("^", "**")
for fname in ["sin", "cos", "exp", "log", "sqrt"]:
pattern = r"{fname} ?([a-zA-Z0-9]*)".format(fname = fname)
replacement = r"math.{fname}(\1)".format(fname = fname)
expression = re.sub(pattern, replacement, expression)
variables = ", ".join(variables)
mathExpr = expression
funCode = functionBaseCode.format(
variables = variables,
mathExpr = mathExpr)
# print(funCode)
definitions = {}
eval(compile(funCode, "<string>", "exec"), globals(), definitions)
f = definitions["f"]
return f
f = generateFunctionFromExpression("t^2 * sint + u*(20 + t) + v*t", "t u v".split())
g = generateFunctionFromExpression("x^2 + y^2", ["x", "y"])
# h = generateFunctionFromExpression("sqrt(x^2 + y^2)")
# l = generateFunctionFromExpression("log(sqrt(x)) - log(x) / 2", ["x"])
# h and l would fail because of the parenthesis after sqrt and log.
print(f(1, 1, 1)) # 22.8414
print(g(2, 3)) # 13