python Sympy表达式中只有负指数

mmvthczy  于 2023-05-05  发布在  Python
关注(0)|答案(2)|浏览(94)

在sympy中,我用大量的除法和乘法来表示表达式,但是对于相同的表达式,扩展的打印结果会有所不同,因为sympy有时使用分数1/x**2,有时使用负指数x**(-2)

from sympy import symbols
x = symbols('x')

print(expand((3+x)/x/x))
print(expand((1+x)/x/x))

输出:

1/x + 3/x**2
1/x + x**(-2)

给定一个表达式e,我怎样才能强制sympy将它只转换为负指数呢?(也许反之亦然,如何转换成分数只?)

ee7vknir

ee7vknir1#

实现这一点的一种方法是通过子类化StrPrinter并应用修改。
注意事项:
1.改装打印机绝非易事。虽然您的编辑看起来非常简单,但它可能需要比这里发布的简单代码更多的工作!请务必深入研究StrPrinter的源代码,查看_print_Mul_print_Pow方法以了解其逻辑的复杂性。此外,请查看源代码中的相应测试,以充分理解像这样的简单编辑可能会在其他地方产生问题。
1.我只会向你们展示它对你们的两个表情有效。如果它在一般情况下不起作用,那么您需要改进它。另外,我将只展示如何将1/x**2打印为x**(-2)。至于其他的,自己试试吧:)
1.下面的代码块可以在Jupyter Notebook上运行,所以你可以只执行some_expression而不是print(some_expression)。如果您要调用print(some_expression),由于某种原因,自定义打印机将不会被调用。

from sympy import *
from sympy.printing import StrPrinter

class MyStrPrinter(StrPrinter):
    def _print_Mul(self, expr):
        if any(isinstance(a, Pow) and (a.exp < 0) for a in expr.args):
            return "*".join([self._print(a) for a in expr.args])
        return super()._print_Mul(expr)
    def _print_Pow(self, expr, rational=False):
        if isinstance(expr.exp, Integer) and (expr.exp < 0):
            return "%s**(%s)" % (expr.base, expr.exp)
        return super()._print_Pow(expr, rational=rational)

def my_str_printer(expr, **kwargs):
    return MyStrPrinter().doprint(expr)

init_printing(use_latex=False, pretty_print=False, str_printer=my_str_printer)

x = symbols("x")
e1 = expand((3+x)/x/x)
e2 = expand((1+x)/x/x)

然后,在不同的单元格上:

e1
# out: x**(-1) + 3*x**(-2)
e2
# out: x**(-1) + x**(-2)
bpzcxfmw

bpzcxfmw2#

由于打印机已经知道如何打印指数,如果您修改表达式以使用Symbol而不是Rational来打印指数,那么它将按照您的要求打印。下面是一个技巧,这样打印机就可以正确地打印表达式:

exp_hack = lambda e: e.replace(
    lambda x: x.is_Pow and x.exp.is_Rational and x.exp<0,
    lambda x: x.base**Symbol(str(x.exp)))
>>> exp_hack((1 + x)/x**2)
x**-2*(x + 1)
>>> exp_hack(expand((1 + x)/x**2))
x**-1 + x**-2
>>> exp_hack(1/sqrt(x))
x**-1/2

相关问题