Python 3.6(Jupyter Notebook)中负立方根为何有时转为复数?
为什么Python中
(-64)**(1/3)返回复数? 先把你的代码和输出贴出来方便对照:
print(-8) print(-8**(1/3)) print(-64**(1/3)) print((-8*8)) print((-8*8)**(1/3))
输出:
-8 -2.0 -3.9999999999999996 -64 (2+3.464101615137754j)
我来拆解这里面的两个核心逻辑:
1. 运算符优先级:负号和幂运算的顺序
你看到的-8**(1/3)和-64**(1/3),其实并不是先算-8再求立方根,而是先算幂运算,再取负号。因为在Python的运算符优先级里,**(幂运算)的优先级比一元负号-更高。
举个例子:
-8**(1/3)等价于-(8**(1/3)):先算8的立方根是2.0,再加负号得到-2.0-64**(1/3)等价于-(64**(1/3)):64的立方根理论上是4,但因为浮点数的二进制精度限制,实际计算会得到近似值3.9999999999999996,取负后就是你看到的结果
这也是为什么这两个表达式能得到实数值的原因——本质上是对正数求立方根再取负,完全在实数域内运算。
2. 负数的分数次幂:Python的复数域处理逻辑
而(-8*8)**(1/3)也就是(-64)**(1/3),是直接对负数做分数次幂运算。这里的核心点是:Python的**运算符在处理负数的非整数次幂时,会返回复数域的主根,而不是实数域的实根。
从数学角度来说,负数的立方根有三个根:一个实根(比如-64的实立方根是-4)和两个共轭复根。但Python的幂运算实现遵循的是复数分析中的主值分支(principal branch),它会返回那个实部为正的复根(也就是你看到的2+3.4641...j),而不是我们直觉里的实根。
为什么Python要这么做?因为对于一般的分数次幂(比如1/2、1/4这种分母为偶数的情况),负数在实数域根本没有定义,所以Python统一用复数域的规则来处理所有负数的非整数次幂,避免出现“有的分数次幂能算,有的不能”的不一致情况。
如何得到负数的实立方根?
如果你的需求是得到负数的实立方根,可以手动处理:先取绝对值求立方根,再加上负号,比如:
x = -64 real_cbrt = -abs(x)**(1/3) print(real_cbrt) # 输出-4.0(或者近似的浮点值)
或者用numpy的cbrt函数,它专门处理实数的立方根,会直接返回实根:
import numpy as np print(np.cbrt(-64)) # 输出-4.0
内容的提问来源于stack exchange,提问作者Yuri Sonovab
相关产品推荐
相关产品推荐

