我在sympy
中有这个表达式
expr = 60378125*139**(13/16)*2143750**(1/8)*x**(9/4)*m**(1/4)/(15420489728*y**(1/4)*z**(3/4))
(注意:这实际上来自其他计算,太长了,不能在这里发布。所以我不确定我是否可以使用任何不同的东西,例如,使用Rational
的替代表达式。
我想去掉所有的数字因子,保留表达式的其余部分,如
expr2 = x**(9/4)*m**(1/4)/(y**(1/4)*z**(3/4))
我怎样才能轻松地做到这一点?
其他答案也很好,但这里有更简单的方法:
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
来获取因子并对其进行过滤的方法可以用于更一般的谓词,因此您可以使用它来选择基于某些任意条件的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
你可以使用模式匹配:
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))
您可以使用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))
编辑:支持任何输入字符串,只要parse_exp()
你收到作为你的输入,而不是处理硬编码的一个:
from sympy import symbols, Mul, Pow, nsimplify, parse_expr
x, y, z, m = symbols('x y z m')
# Replace this with the input string you receive
input_str = '60378125*139**(13/16)*2143750**(1/8)*x**(9/4)*m**(1/4)/(15420489728*y**(1/4)*z**(3/4))'
# Parse the string into a Sympy expression
expr = parse_expr(input_str, evaluate=False)
# Simplify the expression, which will convert floating-point numbers to fractions
expr = nsimplify(expr)
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)