我需要計算一個數字的平方根,例如√9 = 3or √2 = 1.4142。我怎樣才能在 Python 中做到這一點?
輸入可能都是正整數,并且相對較小(比如不到十億),但萬一不是,有什么可能會破壞嗎?
注意:這是在 Meta 上討論了一個具有相同標題的現有問題之后對規范問題的嘗試。
有關的
- python中的整數平方根
- 如何找到整數 n 次根?
- Python中x的第n個根有簡寫嗎?
- **(1/2)、math.sqrt 和 cmath.sqrt 之間的區別?
- 為什么 math.sqrt() 對于大數不正確?
- 非常大的數字的Python sqrt限制?
- Python 中哪個更快:x**.5 或 math.sqrt(x)?
- 為什么 Python 給出平方根的“錯誤”答案?(特定于 Python 2)
- 使用 Python 3 的十進制模塊計算第 n 個根
- 如何使用 python 取 -1 的平方根?(專注于 NumPy)
- 平方根的任意精度
uj5u.com熱心網友回復:
選項1: math.sqrt()
math標準庫中的模塊具有計算數字平方根的功能sqrt。它采用任何可以轉換為float(包括int)的型別作為引數并回傳一個float.
>>> import math
>>> math.sqrt(9)
3.0
選項 2:分數指數
冪運算子 ( **)也可用于計算平方根。從數學上講,的平方根a等于a的冪1/2。
冪運算子需要數字型別并匹配二進制算術運算子的轉換規則,因此在這種情況下,它將回傳 afloat或complex數字。
>>> 9 ** (1/2)
3.0
>>> 9 ** .5 # Same thing
3.0
>>> 2 ** .5
1.4142135623730951
(注意:在 Python 2 中,1/2被截斷為,因此您必須強制使用或類似0的浮點運算。請參閱為什么 Python 給出平方根的“錯誤”答案?)1.0/2
這種方法可以推廣到nth root,盡管不能精確表示為 a 的分數float(如 1/3 或任何不是 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)因為指數比負更緊密的結合。
同時,math只為浮點數構建,所以對于x<0,math.sqrt()將 raise ValueError: math domain error,對于 complex x,它會 raise TypeError: can't convert complex to float。相反,您可以使用cmath.sqrt(),它比求冪更準確(并且可能也會更快):
>>> import cmath
>>> cmath.sqrt(-25)
5j
>>> cmath.sqrt(8j)
(2 2j)
精確
這兩個選項都涉及到的隱式轉換float,因此浮點精度是一個因素。例如:
>>> n = 10**30
>>> square = n**2
>>> x = square**.5
>>> x == n
False
>>> x - n # how far off are they?
0.0
>>> int(x) - n # how far off is the float from the int?
19884624838656
非常大的數字甚至可能不適合浮點數,你會得到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')
Meanwhile, math and cmath will silently convert their arguments to float and complex respectively, which could mean loss of precision.
decimal also has its own .sqrt(). See also calculating n-th roots using Python 3's decimal module
uj5u.com熱心網友回復:
SymPy
根據您的目標,盡可能長時間地延遲平方根的計算可能是個好主意。SymPy可能會有所幫助。
SymPy 是一個用于符號數學的 Python 庫。
import sympy
sympy.sqrt(2)
# => sqrt(2)
起初這似乎不是很有用。
但 sympy 可以提供比浮點數或小數更多的資訊:
sympy.sqrt(8) / sympy.sqrt(27)
# => 2*sqrt(6)/9
此外,不會丟失任何精度。(√2)2 仍然是整數:
s = sympy.sqrt(2)
s**2
# => 2
type(s**2)
#=> <class 'sympy.core.numbers.Integer'>
相比之下,浮點數和小數會回傳一個非常接近 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
uj5u.com熱心網友回復:
數字貨幣
>>> import numpy as np
>>> np.sqrt(25)
5.0
>>> np.sqrt([2, 3, 4])
array([1.41421356, 1.73205081, 2. ])
檔案
消極的
對于負實數,它將回傳nan,因此np.lib.scimath.sqrt()適用于這種情況。
>>> a = np.array([4, -1, np.inf])
>>> np.sqrt(a)
<stdin>:1: RuntimeWarning: invalid value encountered in sqrt
array([ 2., nan, inf])
>>> np.lib.scimath.sqrt(a)
array([ 2. 0.j, 0. 1.j, inf 0.j])
當然,另一種選擇是先轉換為復數:
>>> a = a.astype(complex)
>>> np.sqrt(a)
array([ 2. 0.j, 0. 1.j, inf 0.j])
uj5u.com熱心網友回復:
二進制搜索
免責宣告:這是針對更專業的用例。此方法可能并非在所有情況下都實用。
好處:
- 可以找到整數值(即哪個整數是根?)
- 無需轉換為浮點數,因此精度更高(也可以做得很好)
我個人為加密 CTF 挑戰(RSA 立方根攻擊)實作了這個,我需要一個精確的整數值。
一般的想法可以擴展到任何其他根。
def int_squareroot(d):
left, right = 1, (d 1)//2
while left!=right-1:
x = (left right)//2
if x**2 > d:
left, right = left, x
else:
left, right = x, right
return left
uj5u.com熱心網友回復:
牛頓法
計算平方根最簡單和準確的方法是牛頓法。
你有一個數字,你想計算它的平方根 ( num) 并且你猜測它的平方根 ( estimate)。Estimate 可以是任何大于 0 的數字,但有意義的數字會顯著縮短遞回呼叫深度。
new_estimate = (estimate num/estimate) / 2
這條線使用這兩個引數計算更準確的估計。您可以將new_estimate值傳遞給函式并計算另一個new_estimate比前一個更準確的值,或者您可以像這樣進行遞回函式定義。
def newtons_method(num, estimate):
# Computing a new_estimate
new_estimate = (estimate num/estimate) / 2
print(new_estimate)
# Base Case: Comparing our estimate with built-in functions value
if new_estimate == math.sqrt(num):
return True
else:
return newtons_method(num, new_estimate)
例如,我們需要找到 30 的平方根。我們知道結果在 5 到 6 之間。
newtons_method(30,5)
數字是 30,估計是 5。每個遞回呼叫的結果是:
5.5
5.477272727272727
5.4772255752546215
5.477225575051661
最后一個結果是對數字平方根的最準確計算。它與內置函式的值相同math.sqrt()。
此答案最初由gunesevitan發布,但現在已被洗掉。
uj5u.com熱心網友回復:
Python 的fractions模塊及其類,Fraction用有理數實作算術。該類Fraction沒有實作平方根運算,因為大多數平方根都是無理數。但是,它可以用于以任意精度逼近平方根,因為 aFraction的分子和分母是任意精度整數。
以下方法采用正數x和迭代次數,并回傳 的平方根的上限和下限x。
from fractions import Fraction
def sqrt(x, n):
x = x if isinstance(x, Fraction) else Fraction(x)
upper = x 1
for i in range(0, n):
upper = (upper x/upper) / 2
lower = x / upper
if lower > upper:
raise ValueError("Sanity check failed")
return (lower, upper)
有關此操作的實作的詳細資訊,請參閱下面的參考。它還展示了如何實作具有上限和下限的其他操作(盡管那里的操作顯然至少存在一個錯誤log)。
- Daumas, M.、Lester, D.、Mu?oz, C.,“驗證實數計算:區間算術庫”,arXiv:0708.3721 [cs.MS],2007。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/419288.html
標籤:
上一篇:Python3.9.9-如何計算一個陣列中兩項(t和t 1)的除法對數
下一篇:如何使用模(%)換行字符
