Python里面有內置(Built-in)的平方根函數:sqrt(),可以方便計算正數的平方根。那么,如果要自己定義一個sqrt函數,該怎么解決呢?
解決思路:
1. 大於等於1的正數n的方根,范圍肯定在0~n之間;小於1的正數n的方根,范圍肯定在0~1之間
2. 用二分法(Bisection method, Binary search)從中間開始找n的方根。
3. 對於大於等於1的正數n,先假設n/2是n的方根,如果n/2的平方大於n,那么說明n的方根在0~n/2之間;如果n/2的平方小於n,說明n的方根在n/2~n之間。以此類推。。
4. 對於小於1的正數n,先假設0.5是n的方根,方法同上
這樣做的好處是,每次都可以去掉一半可能的值。因此,搜索的范圍越來越小。
I------------------------I-------------------------I
0 n/2 n
舉例來說,如果是求8的平方根,那么先假設8的平方根是4;
4的平方是16,16大於8,因此8的平方根范圍縮小到0~4之間;
繼續假設8的平方根是2,2的平方是4,4小於8,因此8的平方根范圍縮小到2~4之間;
繼續假設8的平方根是3,3的平方是9,9大於8,因此8的平方根范圍縮小到2~3之間;
以此類推。。。
代碼如下:
def sqrt_bi(n): '''為了方便起見,先假設n為正數''' low=0 #設置下限為0 high=max(n,1) #設置上限為n和1之中的最大數,即:如果n>=1,那么上限為n;如果n<1,那么上限為1 guess=(low+high)/2 #先從中間值開始猜 count=1 #設置猜測次數起始值為1 while abs(guess**2-n)>0.00000000000000000001 and count<100: #當猜測值的平方和n本身的差值無限接近誤差值時,循環才會停止;同時設置猜測次數不超過100次 if guess**2<n: #如果猜測值的平方小於n,那么將此設為下限 low=guess else: #如果猜測值的平方大於n,那么將此設為上限 high=guess guess=(low+high)/2 #根據新的上下限,重新進行猜測 count+=1 #猜測次數每次增加1 return guess
* 這里,我將0.00000000000000000001設為epsilon(誤差值,epsilon為接近0值的浮點數)。epsilon越接近0,算出的方根值就越精確。
調用此函數試一下,同時與python自帶的sqrt函數進行對比:
print(sqrt_bi(8))
import math
print(math.sqrt(8))
運行結果如下:
2.82842712474619
2.8284271247461903
python自帶的sqrt函數比sqrt_bi函數還要更精確一些。
參考:麻省理工學院公開課:計算機科學及編程導論 (第5課)