i具有字符串格式的函数 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
使用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')
在每个"罪"之后留出一个空间(额外的空间不会受到伤害(。
这很丑陋,但是您可以在评估它之前使用正则表达式(在某种程度上(格式化该表达式。您可能必须闯入以适应您的需求。
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