问题描述
假设我定义了以下表达式:
Suppose I define the following expression:
poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
打印出来:
6/(25*x + 75) + 1/(5*(x + 3)**2)
关于这个表达我有两个问题.首先,有没有办法让表达式保持我输入的格式?特别是,我可以做些什么来将第一项的分母保留为 25*(x + 3)
?
I have two questions regarding this expression. Firstly, is there a way to keep the expression in the format in which I entered it? In particular, is there something that I could do in order to leave the denominator of the first term as 25*(x + 3)
?
其次,如果我有印刷形式的表达式,分解表达式、重新格式化第一项的分母,然后将其重新组合在一起的最佳方法是什么?理想情况下,我将能够使用一系列 args
调用深入研究表达式以获得第一项的分母,然后使用 factor 函数将其正确分解,如 poly1.args[0].args[1].args[0].factor()
.问题是,由于组成表达式的元组是不可变的,我不能用上面计算的表达式替换一段 poly1
.除了从头开始重建整个表达式之外,还有没有更好的方法来替代因式分解的多项式?
Secondly, if I have the expression in its printed form, what is the best way to break apart the expression, reformat the denominator of the first term, and then put it back together? Ideally I would be able to just dig into the expression using a series of args
calls to get to the denominator of the first term, and then use the factor function to factor it properly, as in poly1.args[0].args[1].args[0].factor()
. The problem is that, since the Tuples making up the expression are immutable, I can't just replace a piece of poly1
with the expression computed above. Is there a better way to substitute in the factored polynomial than just rebuilding the whole expression from scratch?
注意:我宁愿不使用 subs()
方法,因为它会搜索整个表达式,而且似乎在某些情况下您可能希望对不同的您修改的部分.
Note: I'd rather not use the subs()
method, because that searches the entire expression, and it seems like there might be cases where you would want to be very specific about the different pieces you modify.
推荐答案
常量的自动分配是一个 敏感话题.有一个选项可以禁用它,如下所示:
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
或者您可以将 25 包裹在 UnevaluatedExpr
中以防止其与其他术语发生交互.
Or you can wrap 25 in UnevaluatedExpr
to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
或者在分母中使用未评估的乘积 (Mul):
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
或者将分母包裹在 factor_terms
中 -- 一种更温和的 factor
形式,它可以提取系数而不会对表达式造成太多影响.
Or wrap the denominator in factor_terms
-- a gentler form of factor
which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
或者通过引入一个看起来像数字的符号来作弊:
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
建议阅读:防止表达式求值
第二个问题,关于有针对性的替换,在这种笼统的情况下很难回答.必须递归遍历表达式树,重建expr
as expr.func(*args)
其中 args
是 expr.args
,可能被修改.主要问题是您如何知道25*x + 75
的this 实例是应该替换的实例.
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr
as expr.func(*args)
where args
are expr.args
, possibly modified. The main issue is how you will know that this instance of 25*x + 75
is the one that should be replaced.
这篇关于重新格式化 SymPy 中的表达式片段以防止常数系数的分布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!