總結一下一些常用的計算平方根的方法
1. 牛頓法
具體的做法如下:
計算公式如下:
具體的計算程式如下:
double sqrt_(
double x)
return g; }
2. 利用級數進行逼近
微積分中的泰勒級數如下:
這樣,有了這個公式我們可以得到求平方根公式的展開式:
這樣我們可以進行在一定精度內的逼近。
但是這兒存在乙個問題,就是這個公式的收斂問題。它是存在收斂區間的。
所以可以得到最後的**:
double tsqrt(
double x)
//計算[0,2)範圍內數的平方根
return sum; }
double sqrt2(
double x)
//大於2的數要轉化為[0,2)區間上去
return tsqrt(x)*correction; }
3. 平方根倒數速演算法
這是牛頓迭代法的應用。
維基百科介紹
牛頓迭代法是一種求方程的近似根的方法。首先要估計乙個與方程的根比較靠近的數值,然後根據公式推算下乙個更加近似的數值,不斷重複直到可以獲得滿意的精度。其公式如下:
函式:y=f(x)
其一階導數為:y'=f'(x)
則方程:f(x)=0 的第n+1個近似根為
x[n+1] = x[n] - f(x[n]) / f'(x[n])
牛頓迭代法最關鍵的地方在於估計第乙個近似根。如果該近似根與真根足夠靠近的話,那麼只需要少數幾次迭代,就可以得到滿意的解。 現在回過頭來看看如何利用牛頓法來解決我們的問題。求平方根的倒數,實際就是求方程1/(x^2)-a=0的解。將該方程按牛頓迭代法的公式展開為:
x[n+1]=1/2*x[n]*(3-a*x[n]*x[n])
這個方法的乙個關鍵地方還在於起始值的選取。
具體**如下:
float squarerootfloat(
float number)
該方法又叫卡馬克反轉。其中的0x5f3759df的來歷比較複雜,在維基百科中也有介紹。最後的參考中也有介紹。
最後三種方法的測試**如下:
#include
#include
#include
#include
#include
#define timeb timeb
#define abs(x) ((x)>0?(x):-(x))
#define eps 0.0000000001
time_t time_test(
double x,
double *y,
double(*func)(
double))
double sqrt1(
double x)
return g;
}double tsqrt(
double x)
return sum;
}double sqrt2(
double x)
return tsqrt(x)*correction;
}double sqrt3(
double xi)
int main()
return
0; }
結果如下:
第一列是隨機數,第二列是庫函式sqrt, <>中的是時間,y1是方法1,y2是方法2,y3是方法3
看來這三種方法時間都挺快,都小於毫秒
參考:
快速計算平方根
在3d圖形程式設計中,經常要求平方根或平方根的倒數,例如 求向量的長度或將向量歸一化。c數學函式庫中的sqrt具有理想的精度,但對於3d遊戲程式來說速度太慢。我們希望能夠在保證足夠的精度的同時,進一步提高速度。carmack在quake3中使用了下面的演算法,它第一次在公眾場合出現的時候,幾乎震住了...
快速平方根演算法
在3d圖形程式設計中,經常要求平方根或平方根的倒數,例如 求向量的長度或將向量歸一化。c數學函式庫中的sqrt具有理想的精度,但對於3d遊戲程式來說速度太慢。我們希望能夠在保證足夠的精度的同時,進一步提高速度。carmack在quake3中使用了下面的演算法,它第一次在公眾場合出現的時候,幾乎震住了...
整數平方根的計算 二
摘要 演算法 這個程式的主要演算法是牛頓迭代法。他首先得到乙個平方根的初始值,然後使用牛頓迭代法逐步求精,在計算過程中,始終用兩個整數的比表示整數平方根的值。最後,它轉換分數表示的平方根為10進製字串。說明 該文有待完善。效能分析 對比pifast,它的效能仍然不是很好,我特意分析了這個程式各個部分...