如何在 Python 中计算平方根?

新手上路,请多包涵

我需要计算一些数字的平方根,例如 √9 = 3√2 = 1.4142 。我怎样才能在 Python 中做到这一点?

输入可能都是正整数,而且相对较小(比如不到十亿),但以防万一,是否有任何可能会损坏的东西?


有关的

注意:这是 在 Meta 上讨论 一个现有的同名 问题后对一个 规范问题 的尝试。

原文由 wjandrea 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

选项 1: math.sqrt()

标准库中的 math 模块有 一个 sqrt 函数 来计算一个数的平方根。它采用任何 可以转换为 float 的类型(包括 int )作为参数并返回 float

 >>> import math
>>> math.sqrt(9)
3.0

选项 2:分数指数

幂运算符 ( ** ) 或内置的 pow() 函数也可用于计算平方根。从数学上讲, a 的平方根等于 a1/2

幂运算符需要数字类型并匹配 二进制算术运算符的转换规则,因此在这种情况下,它将返回 floatcomplex 数字。

 >>> 9 ** (1/2)
3.0
>>> 9 ** .5  # Same thing
3.0
>>> 2 ** .5
1.4142135623730951

(注意:在 Python 2 中, 1/2 被截断为 0 ,所以你必须用 1.0/2 强制 浮点运算。 平方根的“错误”答案?

此方法可以推广到 nth root ,尽管不能精确表示为 float 的分数(如 13 或任何不是 2 的幂的分母)可能会导致一些不准确:

 >>> 8 ** (1/3)
2.0
>>> 125 ** (1/3)
4.999999999999999

边缘案例

消极而复杂

求幂适用于负数和复数,但结果略有不准确:

 >>> (-25) ** .5  # Should be 5j
(3.061616997868383e-16+5j)
>>> 8j ** .5  # Should be 2+2j
(2.0000000000000004+2j)

注意 -25 上的括号!否则它被解析为 -(25**.5) 因为 取幂比一元取反更紧密

Meanwhile, math is only built for floats, so for x<0 , math.sqrt(x) will raise ValueError: math domain error and for complex x ,它会提高 TypeError: can't convert complex to float 。相反,您可以使用 cmath.sqrt(x) ,它比求幂更准确(并且可能也更快):

 >>> import cmath
>>> cmath.sqrt(-25)
5j
>>> cmath.sqrt(8j)
(2+2j)

精确

这两个选项都涉及到 float 的隐式转换,因此 浮点精度是一个因素。例如:

 >>> n = 10**30
>>> x = n**2
>>> root = x**.5
>>> n == root
False
>>> n - root  # how far off are they?
0.0
>>> int(root) - n  # how far off is the float from the int?
19884624838656

非常大的数字甚至可能不适合 float,您将得到 OverflowError: int too large to convert to float 。请参阅 Python sqrt limit for very large numbers?

其他类型

让我们看看 Decimal 例如:

求幂失败,除非指数也是 Decimal

 >>> decimal.Decimal('9') ** .5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ** or pow(): 'decimal.Decimal' and 'float'
>>> decimal.Decimal('9') ** decimal.Decimal('.5')
Decimal('3.000000000000000000000000000')

Meanwhile, math and cmath will silently convert their arguments to float and complex respectively, which could mean loss of precision.

decimal 也有自己的 .sqrt() 。另见 使用 Python 3 的 decimal 模块计算 n 次根

原文由 wjandrea 发布,翻译遵循 CC BY-SA 4.0 许可协议

同情心

根据您的目标,尽可能长时间地延迟平方根的计算可能是个好主意。 SymPy 可能会有所帮助。

SymPy 是一个用于符号数学的 Python 库。

 import sympy
sympy.sqrt(2)
# => sqrt(2)

起初这似乎不是很有用。

但是 sympy 可以提供比浮点数或小数更多的信息:

 sympy.sqrt(8) / sympy.sqrt(27)
# => 2*sqrt(6)/9

此外,不会丢失精度。 (√2)² 仍然是一个整数:

 s = sympy.sqrt(2)
s**2
# => 2
type(s**2)
#=> <class 'sympy.core.numbers.Integer'>

相比之下,floats 和 Decimals 将返回一个非常接近 2 但不等于 2 的数字:

 (2**0.5)**2
# => 2.0000000000000004

from decimal import Decimal
(Decimal('2')**Decimal('0.5'))**Decimal('2')
# => Decimal('1.999999999999999999999999999')

Sympy 还可以理解更复杂 的示例,例如高斯积分

 from sympy import Symbol, integrate, pi, sqrt, exp, oo
x = Symbol('x')
integrate(exp(-x**2), (x, -oo, oo))
# => sqrt(pi)
integrate(exp(-x**2), (x, -oo, oo)) == sqrt(pi)
# => True

最后,如果需要十进制表示,可以要求比以往任何时候都需要的更多的数字:

 sympy.N(sympy.sqrt(2), 1_000_000)
# => 1.4142135623730950488016...........2044193016904841204

原文由 Eric Duminil 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题