Sympy的订阅限制

las*_*vec 1 python symbolic-math sympy substitution

我正在处理一些较长的方程式,但并不是很复杂,我想使用sympy来简化和“分解”它们。但是我遇到了一些问题。以下是一些最小示例的列表:

问题1:对称

from sympy import *
from __future__ import division
a = symbols('a')
b = symbols('b')
expr = 1/12*b + 1
expr.subs(1/12*b, a)
expr.subs(b*1/12, a)
Run Code Online (Sandbox Code Playgroud)

第一行给出了预期的结果(即a+1),而第二行则没有替代。

问题2:因式表达式

表达式的某些部分被分解了,当我扩展表达式时,它们被简化了,因此无法进行替换。例如

(((x+1)**2-x).expand()).subs(x**2+2*x, y+1)
Run Code Online (Sandbox Code Playgroud)

会给x^2+x+1,我正在寻找的是y+2-x

有办法解决这些问题吗?还是我应该使用其他符号数学工具?任何建议都欢迎。

asm*_*rer 5

SymPy中有一个主要的陷阱,那就是,由于Python的工作方式,number/number它会给出一个浮点数(或者,如果使用Python 2而不是,则会进行整数除法from __future__ import division)。

在第一种情况下,在您的原始表达式中,Python 1/12*b从左到右求值。1/12由Python计算得出0.08333333333333333,然后乘以b。在第二种情况下,b*1被评估为b。然后b/12由SymPy(因为b是SymPy对象)对其求值,得出Rational(1, 12)*b

由于浮点数的不精确性质,SymPy认为浮点数不0.08333333333333333等于有理数1/12

有这个问题的一些更多的讨论在这里。解决方法是,应避免直接使用integer/integer而不以某种方式包装它,以便SymPy可以创建一个有理数。以下将创建一个合理的:

b/12
Rational(1, 12)*b
S(1)/12*b
Run Code Online (Sandbox Code Playgroud)

因为(((x+1)**2-x).expand()).subs(x**2+2*x, y+1)问题是x**2 + 2*x没有完全出现在表达式中x**2 + x + 1。SymPy通常只替换它所看到的东西。

看来您不介意添加和减去an x来进行替换工作。因此,我建议改为这样做(((x+1)**2-x).expand()).subs(x**2, y+1 - 2*x)。通过仅替换单个术语(x**2),替换将始终有效,并且2*x将会取消以保留x剩余的任何术语(在这种情况下为-x)。