在较大的分数中收集分数表达式(sympy)

Collecting a fraction expression within a larger fraction (sympy)

我正在使用 IPython(Anaconda 发行版)和 sympy 符号数学库。

我有以下表达式:

       t⋅(h + l)       
───────────────────────
l⋅(h + l⋅sin(θ))⋅cos(θ)

我想根据 (h/l)(t/l) 重新排列它:

    (t/l)⋅((h/l)+1)
─────────────────────
((h/l)+sin(θ))⋅cos(θ)

这很容易手工完成;只需将分数两边除以 l 并重新排列即可。

到目前为止,我还没有使用 sympy 的内置函数。

我试过使用 expand 后跟 collect(expr,h/l),但它不会改变表达式。我怀疑这行不通,因为 没有 没有 h/l 条款可以收集。

如何让 sympy 执行此操作?

Python 第一个表达式代码为您节省时间: t*(h + l)/(l*(h + l*sin(theta))*cos(theta))

我真的不知道你是否可以使用正则表达式,但如果可以,你可以使用 re.subh 的所有实例替换为 (h/1)。或者如果表达式是一个字符串,您可以使用 str.replace 来做同样的事情。

所以我使用了 x = h/ly = t/l 并进行了替换。然后简化。这给了我

       x*(y + 1)/((y + sin(theta))*cos(theta))

我想这就是你想要的。我看不出如何简化 "with respect to" h/l 但这行得通...

基于 strubbly 的想法:

In [2]: expr = t *(h +l )/(l *(h +l *sin (theta ))*cos (theta ))

In [3]: expr
Out[3]: 
           t*(h + l)           
-------------------------------
l*(h + l*sin(theta))*cos(theta)

In [4]: repl1 = [x-h/l, y-t/l]

In [7]: repl2 = solve(repl1, t, l)

In [8]: repl2
Out[8]: 
    h     h*y 
{l: -, t: ---}
    x      x  
In [9]: simplify(expr.subs(repl2)).subs({x: h/l, y: t/l})
Out[9]: 
            /h    \          
          t*|- + 1|          
            \l    /          
-----------------------------
  /h             \           
l*|- + sin(theta)|*cos(theta)
  \l             /   

即引入两个变量xy来代替h/lt/l (In[4]),反转等式以获得替换字典 (In[7])。替换、简化(去掉 l),然后将 xy[=25 替换回原始值=].一个变量仍然被简化了。

应该告诉 .subs( ... ) 不要在替换后计算表达式。不知道现在支持不支持

除非您将这些比率放在一起,否则领先的分数将穿过分界线。有两种 glom 方法:使用 UnevaluatedExpr 和使用“符号欺骗”。首先是 UnevaluatedExpr:

>>> from sympy import UnevaluatedExpr as UE
>>> eq
t*(h + l)*cos(th)/(l*(h + l*sin(th)))
>>> factor_terms(_.subs(t, UE(t/l)*l).subs(h, UE(h/l)*l))
cos(th)*(sin(th) + h/l)**(-1)*(1 + h/l)*(t/l)

请注意顺序与您希望的不一样。所以现在用 看起来 像 UE 的符号替换那个 UE:

>>> _.replace(lambda x: isinstance(x, UE), lambda x: Symbol(str(x)))
t/l*(h/l + 1)*cos(th)/(h/l + sin(th))

所以这看起来像你想要的。 t/lh/l 实际上是具有复杂名称的符号。 (您甚至可以使用乳胶作为符号名称。)