SymPy 和复数的平方根
SymPy and square roots of complex numbers
当使用 solve
计算二次方程的根时,SymPy returns 表达式可以简化,但我无法简化它们。一个最小的例子如下所示:
from sympy import *
sqrt(-24-70*I)
在这里,SymPy 只是 returns sqrt(-24-70*I)
,而 Mathematica 或 Maple 将用 5-7*I
.
的等价物回答
我知道有两个平方根,但是这种行为意味着 SymPy 将 return 来自
的非常复杂的解决方案
z = symbols("z")
solve(z ** 2 + (1 + I) * z + (6 + 18 * I), z)
再一次,Maple 和 Mathematica 会很乐意给我求解这个方程的两个高斯整数。
有没有我遗漏的选项或东西?
如果你有mpmath包,你可以做类似
的事情
from sympy import *
import mpmath
a = -24-70*I
b = mpmath.mpc(re(a), im(a)) # a as mpmath.mpc object
c = mpmath.sqrt(b)
d = simplify(c) # Convert back to sympy object
print(d) # 5.0 - 7.0*I
请注意,可能有更便宜的方法(比 simplify
)将转换回 sympy 对象。
更新
正如评论中所指出的,这执行的是数值评估,而不是符号评估。也就是说,上面的其实并不比这个优越:
import cmath
result = cmath.sqrt(-24 - 70j)
print(result) # 5 - 7j
以上有两个有趣的方面。首先,cmath
模块是标准库的一部分。其次,由于 result
是以整数形式给出的,我们可以保证 result
实际上是准确的符号值(并且它可以很容易地转换为 sympy 对象)。如果解是非整数,则 result
表示为浮点数。这当然不是符号复数平方根问题的一般好的解决方案,但如果您事先知道解决方案是整数,它会很有用。
求 z 的平方根在逻辑上与求解方程式 (x+I*y)**2 = z 相同。所以你可以这样做:
from sympy import *
z = -24-70*I
x, y = symbols('x y', real=True)
result = solve((x+I*y)**2 - z, (x, y))
结果是[(-5, 7), (5, -7)]
为方便起见,可以将其包装为一个函数:
def my_sqrt(z):
x, y = symbols('x y', real=True)
sol = solve((x+I*y)**2 - z, (x, y))
return sol[0][0] + sol[0][1]*I
现在您可以使用 my_sqrt(-24-70*I)
并获得 -5 + 7*I
同样的策略有助于您使用二次方程的示例:
x, y = symbols('x y', real=True)
z = x + I*y
solve(z ** 2 + (1 + I) * z + (6 + 18 * I), (x, y))
输出:[(-3, 3), (2, -4)]
另一种解决方法是使用:
sqrt(-24-70*I).as_real_imag()
这个 returns 列表中的实部和虚部,可以进一步处理以恢复复数。
奇怪的是,没有要求计算复数平方根的内置方法。
当使用 solve
计算二次方程的根时,SymPy returns 表达式可以简化,但我无法简化它们。一个最小的例子如下所示:
from sympy import *
sqrt(-24-70*I)
在这里,SymPy 只是 returns sqrt(-24-70*I)
,而 Mathematica 或 Maple 将用 5-7*I
.
我知道有两个平方根,但是这种行为意味着 SymPy 将 return 来自
的非常复杂的解决方案z = symbols("z")
solve(z ** 2 + (1 + I) * z + (6 + 18 * I), z)
再一次,Maple 和 Mathematica 会很乐意给我求解这个方程的两个高斯整数。
有没有我遗漏的选项或东西?
如果你有mpmath包,你可以做类似
的事情from sympy import *
import mpmath
a = -24-70*I
b = mpmath.mpc(re(a), im(a)) # a as mpmath.mpc object
c = mpmath.sqrt(b)
d = simplify(c) # Convert back to sympy object
print(d) # 5.0 - 7.0*I
请注意,可能有更便宜的方法(比 simplify
)将转换回 sympy 对象。
更新
正如评论中所指出的,这执行的是数值评估,而不是符号评估。也就是说,上面的其实并不比这个优越:
import cmath
result = cmath.sqrt(-24 - 70j)
print(result) # 5 - 7j
以上有两个有趣的方面。首先,cmath
模块是标准库的一部分。其次,由于 result
是以整数形式给出的,我们可以保证 result
实际上是准确的符号值(并且它可以很容易地转换为 sympy 对象)。如果解是非整数,则 result
表示为浮点数。这当然不是符号复数平方根问题的一般好的解决方案,但如果您事先知道解决方案是整数,它会很有用。
求 z 的平方根在逻辑上与求解方程式 (x+I*y)**2 = z 相同。所以你可以这样做:
from sympy import *
z = -24-70*I
x, y = symbols('x y', real=True)
result = solve((x+I*y)**2 - z, (x, y))
结果是[(-5, 7), (5, -7)]
为方便起见,可以将其包装为一个函数:
def my_sqrt(z):
x, y = symbols('x y', real=True)
sol = solve((x+I*y)**2 - z, (x, y))
return sol[0][0] + sol[0][1]*I
现在您可以使用 my_sqrt(-24-70*I)
并获得 -5 + 7*I
同样的策略有助于您使用二次方程的示例:
x, y = symbols('x y', real=True)
z = x + I*y
solve(z ** 2 + (1 + I) * z + (6 + 18 * I), (x, y))
输出:[(-3, 3), (2, -4)]
另一种解决方法是使用:
sqrt(-24-70*I).as_real_imag()
这个 returns 列表中的实部和虚部,可以进一步处理以恢复复数。
奇怪的是,没有要求计算复数平方根的内置方法。