我正在编写一个程序,要求用户输入表达式。此表达式作为字符串输入,并使用parse_expr
转换为Sympy表达式。然后我需要获取用户输入的表达式的偏导数。但是,diff
对我正在测试的每个表达式返回0。
例如,如果用户使用以下代码输入a*exp(-b*(x-c)**(2))
,则diff
会返回0
的时间(就我所知diff
而言)返回{{ 1}}在取2*a*b*(c - x)*exp(-b*(x - c)**2)
:
x
我做错了什么?
答案 0 :(得分:1)
底线:使用 parse_expr(str_expr,locals())
。
如果表达式可能使用未导入到本地名称空间且无法访问with the default from sympy import *
的任何实体,也可以添加global_dict=<dict of allowed entities to use>
。
根据Calculus — SymPy Tutorial - SymPy 1.0.1.dev documentation,您可以按原样在diff()
参数中键入符号表达式。由于这些字母是Symbol
个对象(具有重写的运算符),因此在评估参数时,Python会被欺骗构造对应于表达式的SymPy对象!
因此,如果你把它作为一个字符串,你eval
它会触发相同的行为:
<...>
>>> s="a*exp(-b*(x-c)**(2))"
>>> diff(eval(s), x)
−ab(−2c+2x)e−b(−c+x)2
但eval
如果与不受信任的输入一起使用会带来安全隐患,因为它接受任意Python代码。
这就是像parse_expr
这样的替代品发挥作用的地方。但是,由于表达式的解析方式(如上所述),它需要访问表达式中使用的外部实体 - 比如Symbol
对象的变量和所用命名函数的函数对象 - 通过{{1} }和local_dict
参数。
否则,它会动态创建global_dict
个对象。这意味着,它在表达式中为Symbol
创建的Symbol
对象与变量x
不同!难怪它的衍生物是0!
x
答案 1 :(得分:1)
正在开展工作,使sympify
比eval
更安全。最好使用以下内容:
from sympy import *
var ('a b c x')
str_expr = "a*exp(-b*(x-c)**(2))"
parsed_expr = sympify(str_expr)
result = diff(parsed_expr, x)
print(result)
结果:
-a*b*(-2*c + 2*x)*exp(-b*(-c + x)**2)
答案 2 :(得分:0)
将a, b, c, x = symbols('a b c x', real=True)
替换为:
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
x = Symbol('x')
答案 3 :(得分:0)
具有不同假设的符号比较不等:
>>> Symbol('x') == Symbol('x', real=True)
False
当您使用sympify
或parse_expr
时,它会将未知变量解析为符号而不进行假设。在您的情况下,这会创建Symbol('x')
,这与您已创建的Symbol('x', real=True)
不同。
解决方案是删除假设,或者在解析时包含locals()
字典,以便它将名称x
识别为您已定义的Symbol('x', real=True)
,例如
parse_expr(str_expr,locals())
或
sympify(str_expr, locals())