快速浮点开方运算

来源:互联网 发布:java图形界面开发插件 编辑:程序博客网 时间:2024/05/22 00:36

二分法

浮点开方也就是给定一个浮点数x,求根号x。这个简单的问题有很多解,我们从最简单最容易想到的二分开始讲起。利用二分进行开平方的思想很简单,就是假定中值为最终解。假定下限为0,上限为x,然后求中值;然后比较中值的平方和x的大小,并根据大小修改下限或者上限;重新计算中值,开始新的循环,直到前后两次中值的距离小于给定的精度为止。需要注意的一点是,如果x小于1,我们需要将上限置为1,原因你懂的
代码如下:

#define eps 2^(-51)float SqrtByBisection(float n){    float low, up, mid, last;    low = 0, up = (n < 1 ? 1 : n);    mid = (low + up) / 2;    do{        if (mid * mid > n)up = mid;        else low = mid;        last = mid;        mid = (low + up) / 2;    } while (fabsf(mid - last) > eps);    return mid;}

这种方法非常直观,也是面试过程中经常会问到的问题,不过这里有一点需要特别注意:在精度判别时不能利用上下限而要利用前后两次mid值,否则可能会陷入死循环!这是因为由于精度问题,在循环过程中可能会产生mid值和up或low中的一个相同。这种情况下,后面的计算都不会再改变mid值,因而在达不到精度内时就陷入死循环。但是改为判断前后两次mid值就不会有任何问题(为啥自己想)。大家可以找一些例子试一下,这可以算是二分法中的一个trick。二分虽然简单,但是却有一个非常大的问题:收敛太慢!也即需要循环很多次才能达到精度要求。这也比较容易理解,因为往往需要迭代3到4次才能获得一位准确结果。为了能提升收敛速度,我们需要采用其它的方法。

牛顿迭代法

原理也比较简单,就是将中值替换为切线方程的零根作为最终解。原理可以利用下图解释:

牛顿迭代法求开方

这里写图片描述

#define eps 2^(-51)float SqrtByNewton(float x){    float val = x, last;    do{        last = val;        val = (val + x / val) / 2;    } while (fabsf(val - last) > eps);}
原创粉丝点击