学过C或任何一种包含标准库语言的我们,求解一个非负数的平方根自然来的容易,随便调用下类似sqrt的函数就一切ok了!比较喜欢探究的同学也会好奇不用sqrt怎么实现求一个数的平方根,或者说sqrt是如何实现的,这种题目也时常会出现在一些公司的面试中。
本人虽然以前也好奇过,但从未尝试去查询资料探究一番,今有幸看到一公司的面试题提到,遂总结之以加深印象。
1、最笨也最易想到的或许就是暴力破解法了。
通过设定精度,循环测试,以取得在一定精度范围内的平方根。
for(i=0;fabs(x-i*i)>jingdu;i+=jingdu); /*这里jingdu代表允许的精度范围*/
2、牛顿迭代法
很多时候求一个方程f(x)=0的精确解并不容易,而有时求出其近似解也有相当的用处。牛顿迭代法求方程f(x)=0的根的过程:初始化一个x1,通过求f(x)在点(x1,f(x1))处的切线与x轴的交点得x2,然后通过求f(x)在点(x2,f(x2))处的切线与x轴的交点得x3,类似的可能x4,x5,...,xn。当计算次数足够多时,xn->方程f(x)=0的根。这个过程中有迭代关系式Xn=Xn-1-f(Xn-1)/f(x)在Xn-1处的导数。
因此牛顿迭代法求解方程根的思路,我们可以构造函数f(x)=x^2-a=0,从而求得x的平方根。
while (x1!=x0) /*循环条件也可以量实际情况改为在一定精度范围内*/
{
x0 = x1; /* 暂时保存x1的值,以用于下一次循环的判断 */
x1 = 0.5 * (x1 + a / x1); /*即由f(x)=x^2-a=0得迭代关系式,其中a为欲求平方根的非负数 */
}
同样有人综合上述两种方法提出了求解平方根的算法,即先用暴力破解法将x1逼近到一定范围内,再根据牛顿迭代法进行求解,具体代码不再赘述。
3、二分法
对于二分法大家都不陌生,见名大多数估计也知求解平方根的思路了。
求解思路分析(以求3的平方根为例):
(0+3/2=1.5,1.5^2=2.25<3; 说明其平方根在[1.5,3]
(1.5+3)/2=2.25,2.25^2=5.0625>3;说明其平方根在[1.5,2.25]
(1.5+2.25)/2=1.875,1.875^2=3.515625>3;说明其平方根在[1.5,1.875]
...
进行一定的次数,必然可得到3在一定精度范围内的平方根。
C代码如下:
L=mid=0,R=a;/*初始化*/
while(fabs(Lastmid-mid)>jingdu)
{
Lastmid=mid; /*保存mid以用于下一次的循环判断*/
mid=(L+R)/2;
if(mid*mid>a) R=mid;
else L=mid;
}
4、网上同样流传有一神级算法,本人并未研究,在此贴图一份,以供参考。
该算法的详细分析见http://wenku.baidu.com/view/a0174fa20029bd64783e2cc0。