**(1/2)、math.sqrt和cmath.sqrt之间的差异



x**(1/2)math.sqrt()cmath.sqrt()之间有什么区别?

为什么cmath.sqrt()单独得到二次权的复数根?我应该把它专门用于我的平方根吗?他们在后台做什么不同?

如果您分别查看cmath和math的文档,您会发现:

  1. cmath"提供了对复数数学函数的访问"
  2. math"函数不能与复数一起使用;如果需要支持复数,请使用cmath模块中的同名函数。"
  3. (**)运算符映射到pow函数,重要的区别在于pow将其参数转换为float

所以,对于相同的参数,使用三个函数可能会看到不同的结果,如这里所示。请注意,如果表达式有实解,则math.sqrt返回的值与cmath.sqrt返回的值的实部之间不会有差异。但是,如果没有真正的解决方案,math.sqrt会出现错误。

编辑:正如@jermenkoo所指出的,由于/运算符的工作方式不同,(**)返回的值在Python 2和3之间会有差异。但是,如果直接使用0.5而不是1/2,则不应引起问题。

作为对现有答案的补充,一个显著的区别是在处理负数时:

>>> import math
>>> math.sqrt(-4)
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
ValueError: math domain error

sqrt函数仅适用于正值。

>>> (-4)**0.5
(1.2246467991473532e-16+2j)

在这种情况下,**运算符能够返回复数(注意实数部分应该为零的wierd舍入误差)

import cmath
>>> cmath.sqrt(-4)
2j

cmath.sqrt返回完美复数值可能是因为与**相反,sqrt是一个专门的平方根计算,而不仅仅是一个浮点pow函数。

**.5和math.sqrt将几乎相同。

**.5将从标准C库将您发送到powpowhttps://hg.python.org/cpython/file/661195a92131/Objects/floatobject.c#l783和math.sqrt将把您分派到标准C库sqrt中的sqrt,这两个库应该具有相似的性能。之间的差异可能会导致更大的差异

from math import sqrt
sqrt(x)

import math
math.sqrt(x)

只是因为在数学模块中查找CCD_ 19。

cmath不同,并且会更慢。它用于复数的数学运算,这就是它返回复数的原因。请注意,cmath和math之间的区别不同于cPickle和pickle这样的包。

除其他答案外,从性能角度来看,我认为math.sqrti**(1/2)大致相同。

>>> import timeit
>>> import math
>>> 
>>> timeit.timeit(stmt=lambda: [i**(1/2) for i in range(100000)], number=100)
1.5627256259995193
>>> timeit.timeit(stmt=lambda: [math.sqrt(i) for i in range(100000)], number=100)
1.556340146000366
>>> 

cmath.sqrt比它们慢一点:

>>> import cmath
>>> timeit.timeit(stmt=lambda: [cmath.sqrt(i) for i in range(100000)], number=100)
1.9145739509986015

最新更新