第一种方法,使用二分法。在一个区间内每次拿中间数的平方来试,如果大了就左移中间数,如果小了就右移。当结果逼近真实值的时候取精度最高的结果。
//二分法求平方根,首尾两端不断逼近
float Sqrt(float m){
const float eps = 1e-11;
//eps用于控制结果的精度
if(m<0){
cerr<<"无法求根"<<endl;
return -1;
}
float mid,low,up,last;
low = 0,up = m;
mid = (low + up)/2;
do{
if(mid * mid > m)
up = mid;
else
low = mid;
last = mid;
mid = (low + up)/2;
}while(fabs(last - mid) > eps);
//不能使用abs,会提示函数有歧义 ,fabs可以直接传float参数
return mid;
}
第二种方法,牛顿迭代法。↓↓↓↓↓↓↓↓以下描述取自百度百科
设r是
的根,选取
作为r的初始近似值,过点
做
曲线
的切线L,L的方程为
,求出L与x轴交点的横坐标
,称x
1为r的一次近似值。过点
做曲线
的切线,并求该切线与x轴交点的横坐标
,称
为r的二次近似值。重复以上过程,得r的近似值序列,其中,
称为r的
次近似值,上式称为牛顿
迭代公式。












用牛顿迭代法解非线性方程,是把非线性方程
线性化的一种近似方法。把
在点
的某邻域内展开成
泰勒级数
,取其线性部分(即泰勒展开的前两项),并令其等于0,即
,以此作为非线性方程
的近似方程,若
,则其解为
, 这样,得到牛顿迭代法的一个迭代关系式:
。









简单来说就是,如要求A的算术平方根,先假设一个值x,然后不断求(x+a/x)/2=x,不断迭代。
float SqrtByNt(float m){
const float eps = 1e-11;
float x = m;
float last;//用于记录上一次迭代的值
do{
last = x;
x=(x+m/x)/2;
}while(fabs(x-last)>eps);
return x;
}
接下来是卡马克的神奇平方根算法,其实也是用了牛顿迭代法,但他设置了一个神奇的常数0x5f3759df来计算那个猜测值。
float InvSqrt (float x) {
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
return 1/x;
}