首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >防止在SymPy中计算指数

防止在SymPy中计算指数
EN

Stack Overflow用户
提问于 2020-04-17 22:59:23
回答 1查看 114关注 0票数 1

我使用SymPy作为包含许多指数的函数的代码生成器。因此,对于数值稳定性来说,不计算指数的自变量是很重要的。我想防止这种情况发生:

代码语言:javascript
复制
>>> import sympy as sp
>>> x, y = sp.symbols('x y')
>>> expr = sp.exp(5.*x - 10.)
>>> print(expr)
4.53999297624849e-5*exp(5.0*x)

因为它可能导致数值上不准确的结果。

我可以防止指数求值,如下所示:

代码语言:javascript
复制
>>> expr = sp.exp(5.*x - 10., evaluate=False)
>>> print(expr)
exp(5.0*x - 10.0)

但是,当我在表达式上执行诸如替换或微分之类的操作时,将再次计算指数:

代码语言:javascript
复制
>>> expr = sp.exp(5.*x - 10., evaluate=False)
>>> expr.subs(x, y)
4.53999297624849e-5*exp(5.0*y)
>>> expr.diff(x, 1)
5.0*(4.53999297624849e-5*exp(5.0*x))

在这样的操作下,在SymPy中防止指数求值的正确方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-17 23:38:40

最明显的一点是你对整数值使用了浮点数,例如:

代码语言:javascript
复制
In [8]: exp(5*x - 10)                                                                                                             
Out[8]: 
 5⋅x - 10
ℯ        

In [9]: exp(5.*x - 10.)                                                                                                           
Out[9]: 
                     5.0⋅x
4.53999297624849e-5⋅ℯ

也许在你的实际问题中,你想要处理非整数。同样,有理数应该用于精确的计算:

代码语言:javascript
复制
In [10]: exp(Rational(1, 3)*x - S(3)/2)                                                                                           
Out[10]: 
 x   3
 ─ - ─
 3   2
ℯ 

也许您的输入数并不是真正的有理数,您拥有它们作为Python浮点数,但是您希望避免它们求值。您可以使用符号,然后在求值时仅替换符号:

代码语言:javascript
复制
In [13]: exp(a*x + b).evalf(subs={a:5.0, b:10.})                                                                                  
Out[13]: 
 a⋅x + b
ℯ       

In [14]: exp(a*x + b).evalf(subs={x:1, a:5.0, b:10.})                                                                             
Out[14]: 3269017.37247211

In [15]: exp(a*x + b).subs({a:5.0, b:10.})                                                                                        
Out[15]: 
                  5.0⋅x
22026.4657948067⋅ℯ  

如果所有这些看起来都很笨拙,并且您确实只想填充浮点数并阻止求值,那么您可以使用UnevaluatedExpr

代码语言:javascript
复制
In [21]: e = exp(UnevaluatedExpr(5.0)*x - UnevaluatedExpr(10.))                                                                   

In [22]: e                                                                                                                        
Out[22]: 
 x⋅5.0 - 10.0
ℯ            

In [23]: e.doit()    # doit triggers evaluation                                                                                                             
Out[23]: 
                     5.0⋅x
4.53999297624849e-5⋅ℯ 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61274656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档