我需要计算一些数字的平方根,例如\xe2\x88\x9a9 = 3和\xe2\x88\x9a2 = 1.4142。我怎样才能用Python做到这一点?
输入可能都是正整数,并且相对较小(比如小于十亿),但万一它们不是,有什么可能会破坏吗?
\n注意:这是在 Meta 上讨论现有同标题问题后对规范问题的尝试。
\n有关的
\n\n \nwja*_*rea 87
math.sqrt()math标准库中的模块有一个计算sqrt数字平方根的函数。它接受任何可以转换为的float类型(包括int)并返回float。
>>> import math
>>> math.sqrt(9)
3.0
Run Code Online (Sandbox Code Playgroud)
幂运算符 ( **)或内置pow()函数也可用于计算平方根。从数学上来说,的平方根a等于a的次方1/2。
幂运算符需要数字类型并匹配二进制算术运算符的转换规则,因此在这种情况下它将返回 afloat或complex数字。
>>> 9 ** (1/2)
3.0
>>> 9 ** .5 # Same thing
3.0
>>> 2 ** .5
1.4142135623730951
Run Code Online (Sandbox Code Playgroud)
(注意:在 Python 2 中,1/2被截断为0,因此您必须强制使用1.0/2或 类似的浮点算术。请参阅Why does Python Give the “wrong” answer for square root?)
此方法可以推广到nth root,尽管无法精确表示为 a 的分数float(例如 1/3 或任何不是 2 的幂的分母)可能会导致一些不准确:
>>> 8 ** (1/3)
2.0
>>> 125 ** (1/3)
4.999999999999999
Run Code Online (Sandbox Code Playgroud)
求幂适用于负数和复数,但结果有一些轻微的不准确:
>>> (-25) ** .5 # Should be 5j
(3.061616997868383e-16+5j)
>>> 8j ** .5 # Should be 2+2j
(2.0000000000000004+2j)
Run Code Online (Sandbox Code Playgroud)
(注意: 上需要括号-25,否则它会被解析为-(25**.5)因为求幂比求反具有更紧密的绑定。)
同时,math仅针对浮点数构建,因此对于x<0,math.sqrt(x)将引发ValueError: math domain error,对于复杂x,它将引发TypeError: can't convert complex to float。相反,您可以使用cmath.sqrt(x),它比求幂更准确(并且可能也更快):
>>> import cmath
>>> cmath.sqrt(-25)
5j
>>> cmath.sqrt(8j)
(2+2j)
Run Code Online (Sandbox Code Playgroud)
这两个选项都涉及隐式转换float,因此浮点精度是一个因素。例如,让我们尝试一个大数字:
>>> n = 10**30
>>> x = n**2
>>> root = x**.5
>>> root == n
False
>>> root - n # how far off are they?
0.0
>>> int(root) - n # how far off is the float from the int?
19884624838656
Run Code Online (Sandbox Code Playgroud)
非常大的数字甚至可能无法放入浮点数中,您会得到OverflowError: int too large to convert to float. 看到Python sqrt限制非常大的数字?
让我们看一下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')
Run Code Online (Sandbox Code Playgroud)
同时,math和cmath会默默地将它们的参数分别转换为float和complex,这可能意味着精度损失。
decimal也有自己的.sqrt()。另请参阅使用 Python 3 的十进制模块计算 n 次根
Eri*_*nil 24
根据您的目标,尽可能延迟平方根的计算可能是个好主意。SymPy可能会有所帮助。
\n\n\nSymPy 是一个用于符号数学的 Python 库。
\n
import sympy\nsympy.sqrt(2)\n# => sqrt(2)\nRun Code Online (Sandbox Code Playgroud)\n乍一看这似乎不太有用。
\n但 sympy 可以提供比浮点数或小数更多的信息:
\nsympy.sqrt(8) / sympy.sqrt(27)\n# => 2*sqrt(6)/9\nRun Code Online (Sandbox Code Playgroud)\n而且,精度不会丢失。(\xe2\x88\x9a2)\xc2\xb2 仍然是一个整数:
\ns = sympy.sqrt(2)\ns**2\n# => 2\ntype(s**2)\n#=> <class \'sympy.core.numbers.Integer\'>\nRun Code Online (Sandbox Code Playgroud)\n相比之下,浮点数和小数将返回一个非常接近 2 但不等于 2 的数字:
\n(2**0.5)**2\n# => 2.0000000000000004\n\nfrom decimal import Decimal\n(Decimal(\'2\')**Decimal(\'0.5\'))**Decimal(\'2\')\n# => Decimal(\'1.999999999999999999999999999\')\nRun Code Online (Sandbox Code Playgroud)\nSympy 还可以理解更复杂的示例,例如高斯积分:
\nfrom sympy import Symbol, integrate, pi, sqrt, exp, oo\nx = Symbol(\'x\')\nintegrate(exp(-x**2), (x, -oo, oo))\n# => sqrt(pi)\nintegrate(exp(-x**2), (x, -oo, oo)) == sqrt(pi)\n# => True\nRun Code Online (Sandbox Code Playgroud)\n最后,如果需要十进制表示,则可以要求比实际需要更多的数字:
\nsympy.N(sympy.sqrt(2), 1_000_000)\n# => 1.4142135623730950488016...........2044193016904841204\nRun Code Online (Sandbox Code Playgroud)\n
wja*_*rea 15
>>> import numpy as np
>>> np.sqrt(25)
5.0
>>> np.sqrt([2, 3, 4])
array([1.41421356, 1.73205081, 2. ])
Run Code Online (Sandbox Code Playgroud)
对于负实数,它将返回nan,因此np.emath.sqrt()适用于这种情况。
>>> a = np.array([4, -1, np.inf])
>>> np.sqrt(a)
<stdin>:1: RuntimeWarning: invalid value encountered in sqrt
array([ 2., nan, inf])
>>> np.emath.sqrt(a)
array([ 2.+0.j, 0.+1.j, inf+0.j])
Run Code Online (Sandbox Code Playgroud)
当然,另一种选择是先转换为复数:
>>> a = a.astype(complex)
>>> np.sqrt(a)
array([ 2.+0.j, 0.+1.j, inf+0.j])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
65100 次 |
| 最近记录: |