这次我们来学习一下如何求平方根。在计算机中很难有精确的求出数据的平方根的算法,基本都是要求一个误差可接受范围内的近似值。治理我们取误差值为1e-5。
笔者的编程语言及环境如下
- 编程语言:c++
- 编译器:Code Blocks
- 系统: windows 10 x64
二分法
二分法求平方根的思路如下:
- 设置一个初始区间[0,n],若n<1则初始区间为[0,1]。
- 取区间中值mid的平方与数据n比较。
- 若数据n小则令区间变为[0,mid];否则变为[mid,n(或1)]。
- 若先后两次中值的差在误差范围内,则此次mid为平方根的近似值。
代码如下:
double sqrt(double number)//二分法
{
double low=0.0,high=number>1?number:1;
double mid=0,last=0;
do{
last=mid;
mid=(low+high)/2;
if(mid*mid>number)high=mid;
else low=mid;
}while(fabs(mid-last)>1e-5);
return mid;
}
以123456789012为测试数据结果如下
递归法(牛顿法)
迭代法求平方根的主要思路为:
- 令x为任意值(通常取数据n的一半)。
- 令y=(x+n/x)/2。
- 若x与y的差在误差范围内,则y为平方根近似值;否则令x=y执行第2步
代码如下:
double sqrt1(double number,double x)
{
double y=(x+number/x)/2;
return fabs(y-x)<0.001?y:sqrt1(number,y);
}
以123456789012测试结果如下:
卡马克法
可以在上文看到牛顿迭代算法的初值是任意的,一个好的初值可以大大降低迭代次数。卡马克算法所求的是平方根的倒数(在实际应用中平方根的倒数比平方根用的多)。卡马克算法可以理解为优化的迭代算法,其选择了一个极好的初值,将算法优化到一次或两次迭代就可以达到误差范围内。因为其涉及到浮点数在计算机内的存储方式及Magic Number,这里将不再赘述,有兴趣的可以自行百度。
因为其涉及到浮点数的存储,而系统中float与double的存储不一样,所以有float与double两种版本。
float版代码如下:
float sqrt