感谢杨工,让我更加认识到自己技术薄弱,这道题源自于和杨工的非正式面试,当时根本没思路,甚至没和查找有丝毫的联系,看来做自己想做的还是要付出努力的。sqrt()即开平方运算,y=x*x,已知Y的情况下求解X的值,基本的思路是找个区间,逐步计算逼近,知道需要的精度。

(1)二分查找

并不是严格的二分查找,设定寻找的区间,在这个区间中一直取中点,计算中点的平方和Y的查找,逐步逼近,直到自己需要的精度:

#define  ABS_FLOAT 0.000001
bool eqs(double val1 , double val2)
{
double diff = fabs(val1 - val2) ;
if(diff < ABS_FLOAT)
{
return true ;
}
else
{
return false ;
}
} //获取开方值,二分查找的方法
double SqrtBybisection(double _value)
{
if (_value <= 0 )
return 0 ; double low = 0.0;
double high = 0.0 ; if (_value > 0 && _value < 1)
{
low = _value;
high = 1.0 ;
}
else
{
low = 1.0 ;
high = _value ;
} double mid = (low + high)/2.0 ;
double last = 0.0 ; do
{
if (mid * mid > _value)
{
high = mid ;
}
else
{
low = mid ;
} last = mid ;
mid = (high + low )/ 2.0 ; //std::cout << mid << std::endl ; }while(! eqs( last , mid)) ; return mid ;
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

2 牛顿迭代法

  

    牛顿迭代法通过泰勒公司展开,通过切线逐步逼近,具体推到可以参考:牛顿逼近 , sqrt实现的代码:

//牛顿迭代法求解
/* f(x) = x^2 - v --> x = x0 - f(x0)/2x0 -->x = (x0 + v / x0) / 2 ;
-->
*/
double SqrtByNewton(const double& _val)
{
double nrt = _val ;
double last_nrt = 0 ;
while (! eqs( nrt , last_nrt))
{
last_nrt = nrt ;
nrt = (nrt + _val / nrt) / 2.0 ;
}
return nrt ;
}

3 技巧算法

看到这种解法,我也很惊讶,程序员真是无底线啊~~

先看看浮点数表示,浮点数不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。

数学中浮点用S=M*2^N, 在计算机中 主要由三部分构成:符号位+指数位(N)+尾数(M),符号位:0为正1为负,指数位:2^M ,移位存储,尾数:即有效数字,规定整数部分为1

float 浮点数内存分布:

31 30~23 22~0
1 位 符号位 8位 指数位 23位 尾数
double型浮点内存分布:
63 62~52 51~0
1 位 符号位 11位 指数位 52位 尾数
 
比如 float类型8.5,二进制表示为1000.1 ,标准表达为1.0001*2^3 , OK ,该数的指数位:127+3=130,即10000010 ,符号位 0, 尾数去掉1为0001 ,填充后为0001 0000 0000 0000 0000 000,这个数的表示为 1 1000010 0001  0000 0000 0000 0000 0000 000
符号位 指数位 尾数
0 10000010 0001 0000 0000 0000 0000 000
了解这些之后,再来看一下快速的技巧:
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

float sqrtinv(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (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
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy return 1/x;
}
 

这个算法速度据说比系统函数还要快,确实,迭代的步骤少来很多,具体解释和浮点的表示有关,可以参考下文:一般而言,一个float数据 共32个bit,和int数据一样。其中前23位为有效数字 ,后面接着一个8位数据 表示指数,最后一位表示符号,由于这里被开方的数总是大于0,所以我们暂不考虑最后一个符号位。此时

如果我们把计算机内的浮点数 看做一个整数 ,那么

现在开始逐步分析函数。这个函数的主体有四个语句,分别的功能是:

int i = *(int*)&x; 这条语句把 转成

i = 0x5f3759df - (i>>1); 这条语句从 计算

y = *(float*)&i; 这条语句将 转换为

y = y*(1.5f - xhalf*y*y); 这时候的y是近似解;此步就是经典的牛顿迭代法。迭代次数越多越准确。关键是第二步 i = 0x5f3759df - (i>>1); 这条语句从 计算 原理:

带入之后两边取对数,再利用近似表示

算一算就得到:

若取 就是程序里所用的常量0x5f3759df。至于为何选择这个 ,则应该是曲线拟合实验的结果。

4 测试结果

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

sqrt函数实现的更多相关文章

  1. 转:一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html 源码下载地址:http://diducoder.com/sotr ...

  2. [转载]求平方根sqrt()函数的底层算法效率问题

    我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来实现这个经常调用的函数呢? 虽然 ...

  3. Sqrt函数高效实现

    转自一个Sqrt函数引发的血案 我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来 ...

  4. 一个Sqrt函数引发的血案(转)

    作者: 码农1946  来源: 博客园  发布时间: 2013-10-09 11:37  阅读: 4556 次  推荐: 41   原文链接   [收藏]   好吧,我承认我标题党了,不过既然你来了, ...

  5. 【转载】一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 源码下载地址:http://diducoder ...

  6. 一个Sqrt函数引发的血案

    源码下载地址:http://diducoder.com/sotry-about-sqrt.html 好吧,我承认我标题党了,不过既然你来了,就认真看下去吧,保证你有收获. 我们平时经常会有一些数据运算 ...

  7. sqrt函数实现(神奇的算法)

    我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来实现这个经常调用的函数呢? 虽然 ...

  8. php sqrt()函数 语法

    php sqrt()函数 语法 作用:sqrt()函数的作用是对参数进行求平方根 语法:sqrt(X) 参数: 参数 描述 X 进行求平方根的数字 说明:返回将参数X进行开平方后的结果江苏大理石平台 ...

  9. PHP sqrt() 函数

    实例 返回不同数的平方根: <?phpecho(sqrt(0) . "<br>");echo(sqrt(1) . "<br>"); ...

随机推荐

  1. .NET委托解析

    委托这个概念其实我们都很熟悉了,但是在使用的时候很多人还是无法去把控它,我们可以试想一下,在平时编码的时候,你是直接按照业务逻辑直接创建类,new出一个对象来进行操作的还是说有用到委托来更高效的完成一 ...

  2. JAVA基础学习之String、StringBuffer、StringBuilder、基本数据类型的使用、整形进制转换、集合Collection、Vector、ArrayList、LinkedList、HashSet、TreeSet等(3)

    主函数类MainDemo.java package com.itcast.test20140109; import java.util.ArrayList; import java.util.Coll ...

  3. JAVA 正则表达式、汉字正则、 java正则代码

    转自于:http://blog.csdn.net/q326527970/article/details/7513974 (一)字母.数字.下划线.汉字正则表达式 1. 只有字母.数字和下划线且不能以下 ...

  4. UVALive 6887 Book Club 最大流解最大匹配

    题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...

  5. Codeforces Round #350 (Div. 2) F. Restore a Number 模拟构造题

    F. Restore a Number   Vasya decided to pass a very large integer n to Kate. First, he wrote that num ...

  6. 小甲鱼PE详解之输入表(导出表)详解(PE详解09)

    小甲鱼PE详解之输出表(导出表)详解(PE详解09) 当PE 文件被执行的时候,Windows 加载器将文件装入内存并将导入表(Export Table) 登记的动态链接库(一般是DLL 格式)文件一 ...

  7. 解决:jquery-1.11.1.min.js红叉问题

    工程中导入jquery-1.11.1.min.js,工程正常运行.但是jquery-1.11.1.min.js一直显示红叉. 解决方法如下: 红叉的原因是:myeclipse没有去验证它! 选中js文 ...

  8. Menu菜单

    选项菜单 1.菜单的生命周期 * onCreateOptionsMenu() 选项菜单创建时调用(启动Activity时调用 只调用1次) * onPrepareOptionsMenu() 选项菜单准 ...

  9. XMLSAX解析

    * HTML不区分大小写,XML区分大小写 * 用浏览器打开xml文件,判断xml文件是否有错 * xml与html的区别 1:xml的标记可以自定义,但是html标记不可以定义.<studen ...

  10. XML引入多scheme文件约束简单示例

    XML引入多scheme文件约束简单示例,用company.xsd和department.xsd来约束company.xml: company.xsd <?xml version="1 ...