首页 > 代码库 > 平方根(sqrt)算法
平方根(sqrt)算法
最近听说开平方算法挺难写,自己思考一下确实这些库函数只是一直在用,但是很少去思考如何实现的,sqrt在排序中使用频率非常的高,所以就研究了一下。大概有三种实现方式。
一、用二分的方法
每次用中间数就试,如果大就到左区间选取中间数试,如果小就到右区间找中间数试,采用不断逼近的方式计算平方根,这种方式迭代次数有点多,且每次试验都要进行运算,效率不是很高,但是思路简单,巧妙的运用了二分的方法。
#define eps 0.00000001 float SqrtByBisection(float n) { //小于0的按照你需要的处理 if(n < 0) return n; float mid,last; float low,up; low=0,up=n; mid=(low+up)/2; do { if(mid*mid>n) up=mid; else low=mid; last=mid; mid=(up+low)/2; } //精度控制 while(fabs(mid-last) > eps); return mid; }二、牛顿迭代法
这种方式的原理就是通过f(x) = x^2 - a = 0 的切线来逼近x^2 -a =0的的根,根号a就是f(x) =0的一个正实根,这个函数的导数是2x,也就是切线的斜率是2x,也就是x-f(x)/2x是比x更接近的近似值,带人方程得到f(x) = (x+a/x) / 2是更近似的值
float SqrtByNewton(float x) { float val = x;//最终 float last;//保存上一个计算的值 do { last = val; val =(val + x/val) / 2; }while(fabs(val-last) > 0.0001); return val; }三、神一样的算法
float InvSqrt(float x) { float xhalf = 0.5f*x; int i = *(int*)&x; // get bits for floating VALUE i = 0x5f3759df - (i>>1); // gives initial guess y0 x = *(float*)&i; // convert bits BACK to float x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy return x; }
这个算法是卡马克(quake3作者)实现的,他真正牛B的地方是他选择了一个神秘的常数0x5f3759df 来计算那个猜测值,也是采用牛顿迭代法,但是选择的常数是绝妙的,能降上面的牛顿迭代法效率提高四倍,有空一定要拜读一下quake3的源代码,我在资源中放了一份欢迎下载
平方根(sqrt)算法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。