python 去掉前置因子,而不改变表达式的其余部分

j7dteeu8  于 2023-04-10  发布在  Python
关注(0)|答案(3)|浏览(260)

我在sympy中有这个表达式

expr = 60378125*139**(13/16)*2143750**(1/8)*x**(9/4)*m**(1/4)/(15420489728*y**(1/4)*z**(3/4))

我想去掉所有的数值因子,保留表达式的其余部分,如

expr2 = x**(9/4)*m**(1/4)/(y**(1/4)*z**(3/4))

我怎么能轻易做到这一点?

kognpnkq

kognpnkq1#

其他答案也不错,但这里有更简单的方法:

In [5]: from sympy import symbols, Mul, Rational as R

In [6]: x, y, z, m = symbols('x y z m')

In [7]: expr = (60378125 * 139**R(13,16) * 2143750**R(1,8)
   ...:         * x**R(9,4) * m**R(1,4) / (15420489728 * y**R(1,4) * z**R(3,4)))

In [8]: expr
Out[8]: 
            13                       
            ──                       
            16 8 _________ 4 ___  9/4
60378125⋅139  ⋅╲╱ 2143750 ⋅╲╱ m ⋅x   
─────────────────────────────────────
                    4 ___  3/4       
        15420489728⋅╲╱ y ⋅z          

In [9]: Mul.make_args(expr)
Out[9]: 
⎛                13                                       ⎞
⎜                ──                                       ⎟
⎜  60378125      16  8 _________  4 ___   9/4    1     1  ⎟
⎜───────────, 139  , ╲╱ 2143750 , ╲╱ m , x   , ─────, ────⎟
⎜15420489728                                   4 ___   3/4⎟
⎝                                              ╲╱ y   z   ⎠

In [10]: [f for f in Mul.make_args(expr) if not f.is_number]
Out[10]: 
⎡4 ___   9/4    1     1  ⎤
⎢╲╱ m , x   , ─────, ────⎥
⎢             4 ___   3/4⎥
⎣             ╲╱ y   z   ⎦

In [11]: Mul(*[f for f in Mul.make_args(expr) if not f.is_number])
Out[11]: 
4 ___  9/4
╲╱ m ⋅x   
──────────
4 ___  3/4
╲╱ y ⋅z

这种使用make_args获取因子并过滤它们的方法可以用于更一般的 predicate ,因此您可以使用这种方法基于某些任意条件选择Mul的因子的任何子集。
实际上,你正在尝试做的是一个非常常见的操作,因此有一个特定的方法来做到这一点:

In [19]: expr.as_independent(x, y, z, m, as_Add=False)
Out[19]: 
⎛            13                        ⎞
⎜            ──                        ⎟
⎜            16 8 _________  4 ___  9/4⎟
⎜60378125⋅139  ⋅╲╱ 2143750   ╲╱ m ⋅x   ⎟
⎜──────────────────────────, ──────────⎟
⎜       15420489728          4 ___  3/4⎟
⎝                            ╲╱ y ⋅z   ⎠

In [20]: expr.as_independent(x, y, z, m, as_Add=False)[1]
Out[20]: 
4 ___  9/4
╲╱ m ⋅x   
──────────
4 ___  3/4
╲╱ y ⋅z   

In [21]: expr.as_independent(*expr.free_symbols, as_Add=False)[1]
Out[21]: 
4 ___  9/4
╲╱ m ⋅x   
──────────
4 ___  3/4
╲╱ y ⋅z
v8wbuo2f

v8wbuo2f2#

您可以使用Rational()定义表达式来将指数处理为有理数,然后创建一个列表来存储非数值因子。接下来,使用遍历表达式的因子,并检查因子是否是具有isinstance()的幂。如果是幂,使用as_base_exp()分离基数和指数。检查基数是否是符号而不是数字,以及基数是否是符号或因子是否是符号,将其附加到non_numeric_factors。迭代所有因子后,将non_numeric_factors相乘,结果是一个只包含非数值因子的新表达式:

from sympy import symbols, Mul, Pow, Rational

x, y, z, m = symbols('x y z m')

expr = (60378125 * 139**(Rational(13, 16)) *
        2143750**(Rational(1, 8)) * x**(Rational(9, 4)) *
        m**(Rational(1, 4)) /
        (15420489728 * y**(Rational(1, 4)) * z**(Rational(3, 4))))

non_numeric_factors = []

for factor in Mul.make_args(expr):
    if isinstance(factor, Pow):
        base, exp = factor.as_base_exp()
        if base.is_symbol:
            non_numeric_factors.append(factor)
    elif factor.is_symbol:
        non_numeric_factors.append(factor)

expr2 = Mul(*non_numeric_factors)

print(expr2)

产生

m**(1/4)*x**(9/4)/(y**(1/4)*z**(3/4))
mjqavswn

mjqavswn3#

您可以使用模式匹配:

from sympy import *
var("x, m, y, z")
expr1 = 60378125*139**(13/16)*2143750**(1/8)*x**(9/4)*m**(1/4)/(15420489728*y**(1/4)*z**(3/4))
# converts float numbers to rational numbers
expr1 = nsimplify(expr1)
# pattern matching:
# w1 selects every number
# w2 selects everything that is not a number
w1 = Wild("w1", properties=[lambda t: t.is_Number])
w2 = Wild("w2", exceptions=[lambda t: t.is_Number])
# find a product given by a number and something else
matches = expr1.match(w1 * w2)
# the final expression is just everything else without the factor (number)
expr = matches[w2]
print(expr)
# out: m**(1/4)*x**(9/4)/(y**(1/4)*z**(3/4))

相关问题