如何使用sympy简化包含复数常量的表达式?

9

我已经在sympy中进行了一些计算,最终得出的结果是一组常数。其中一个直接插入到下面的片段中:

from sympy import *
expr = (18**(Rational(1, 3))/(6*(3 + sqrt(3)*I)**(Rational(1, 3)))
        + 12**(Rational(1, 3))*(3 + sqrt(3)*I)**(Rational(1, 3))/12)
print(expr.evalf())
print(expr.simplify())

这将返回:

这将返回

0.56857902130163 + 0.e-22*I
18**(1/3)/(6*(3 + sqrt(3)*I)**(1/3)) + (36 + 12*sqrt(3)*I)**(1/3)/12

因此,该表达式似乎是一个实数,但是sympy无法进一步简化它。用纸笔计算,我将其简化为

cos(pi/18) / sqrt(3)

这与evalf()返回的数值相符。

我尝试了许多不同的简化函数,但似乎没有一种能够进一步简化表达式。使用类似于

expr.subs(3 + sqrt(3)*I, sqrt(12) * exp(I*pi/6))

这句话的意思是Sympy在推导过程中表达式已经变得更好了,但仍然不能确定其是否为实数。可以尝试使用欧拉公式进行替换。

expr.subs(3 + sqrt(3)*I, sqrt(12) * (cos(pi/6) + I*sin(pi/6)))

sympy 终于能够得出结论,表达式是真实的,但是当我尝试 simplify 替换后,表达式本身在打印时会爆炸式增长。

有没有更好的方法来尝试减少这种情况?我有许多类似的复杂常数表达式,我想确定它们是否为真实的(或不是)。

2个回答

5

方法as_real_imag通常有助于简化复数,即使它没有列在简化方法中。在您的示例中,

expr.as_real_imag()

返回结果为 (sqrt(3)*cos(pi/18)/3, 0)

如果需要一个复数(而不是上面的元组),那么就不应该只在这个元组上调用complex,因为这会创建一个Python complex类的对象,涉及数字评估。相反,我会这样写

pair = expr.as_real_imag()
result = pair[0] + pair[1]*I

5

针对您提供的表达式,需运行以下命令:

(expr.conjugate().conjugate() - expr.conjugate()).simplify()

返回 0,表示 expr 是实数。(共轭运算两次会返回原始值,但在此过程中它会被展开,从而使后续简化成为可能。)一般来说,上述公式返回虚部乘以2i。

要找到表达式的实部,您可以使用类似的技巧:将其与其共轭相加并简化(然后除以2):

((expr.conjugate().conjugate()+expr.conjugate())/2).simplify()

返回值为 sqrt(3)*cos(pi/18)/3

1
这对于我举的例子表达式效果很好。更简单的方法是expr.conjugate().conjugate().simplify().trigsimp(),它可以直接输出结果。然而,对于更复杂的表达式,这种共轭方法并不是很有效,但仍然有用。 - josteinb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接