在sympy中,如何获取有理数表达式的系数?

3

我有一个有理(这里是双线性的)表达式,想要使用sympy来收集系数。但是应该怎么做呢?

from sympy import symbols, Wild, pretty_print

a, b, c, d, x, s = symbols("a b c d x s")

def coeffs(expr):
    n0 = Wild("n0", exclude=[x])
    n1 = Wild("n1", exclude=[x])
    d0 = Wild("d0", exclude=[x])
    d1 = Wild("d1", exclude=[x])
    match = expr.match((n0 + n1*x) / (d0 + d1*x))
    n0 = n0.xreplace(match)
    n1 = n1.xreplace(match)
    d0 = d0.xreplace(match)
    d1 = d1.xreplace(match)
    return [n0, n1, d0, d1]

if __name__ == '__main__':
    pretty_print(coeffs((a + b*x) / (c + d*x)))
    pretty_print(coeffs(2 * (a + b*x) / (c + d*x)))
    pretty_print(coeffs(s * (a + b*x) / (c + d*x)))

我尝试使用match,但它几乎总是失败的,例如在最后一行(带有“s”的符号前缀)中,我得到了:

Traceback (most recent call last):
  File "...", line 20, in <module>
    pretty_print(coeffs(s * (a + b*x) / (c + d*x)))
  File "...", line 11, in coeffs
    n0 = n0.xreplace(match)
  File "/usr/lib/python3/dist-packages/sympy/core/basic.py", line 1626, in xreplace
    return rule.get(self, self)
AttributeError: 'NoneType' object has no attribute 'get'

因此匹配不成功。

1个回答

4

如果你知道需要考虑的表达式是有理数,你可以将它们的分子和分母提取出来,独立地找到它们的系数。

以下是一种实现方法:

import sympy as sp

def get_rational_coeffs(expr):
    num, denom = expr.as_numer_denom()

    return [sp.Poly(num, x).all_coeffs(), sp.Poly(denom, x).all_coeffs()]

a, b, c, d, x, s = sp.symbols("a b c d x s") 
expr = (a + b*x) / (c + d*x)

# note the order of returned coefficients
((n1, n0), (d1, d0)) = get_rational_coeffs(s*expr)
print(((n0, n1), (d0, d1)))

((a*s, b*s), (c, d))

以上方法也比coeffs更快。在需要expr系数的情况下(coeffs成功的情况下),我得到以下计时结果(基于Jupyter的%timeit魔法):

%timeit get_rational_coeffs(expr)
%timeit coeffs(expr)

1000次循环,3次中最好的表现为每个循环1.33毫秒

1000次循环,3次中最好的表现为每个循环1.99毫秒


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接