偶然看见一段求根的神代码,于是就有了这篇博客;

对于求根问题,通常我们可以调用sqrt库函数,不过知其然需知其所以然,我们看一下求根的方法;

比较简单方法就是二分咯:

代码:

 #include<bits/stdc++.h>
#define MAXN 100000+10
#define MAX 100000000
#define eps 1e-6
#define ll long long
using namespace std; float get_sqrt(float x)
{
float low=, up=x, mid, now;
mid=(low+up)/;
do
{
now=mid; //**now保存上一次计算的值
if(mid*mid<x) //**mid偏小,右移
{
low=mid;
}
else //**mid偏大,左移
{
up=mid;
}
mid=(low+up)/;
}while(abs(mid-now)>eps); //**两次计算的误差小于eps,mid即为所求值
return mid;
} int main(void)
{
std::ios::sync_with_stdio(false), cin.tie(), cin.tie();
float x;
cin >> x;
cout << get_sqrt(x) << endl;
return ;
}

然而虽然其计算的结果和库函数一样,然而其效率较之库函数差数百倍,当然不是我说的神代码咯;

我们再看一下牛顿迭代法如何;

假设a为需求根的数,x为其正根,则有a=x*x;即a的正根为函数f(x)=x*x-a与x轴的正交点;

由牛顿迭代法我们可以知道,可以通过(x,f(x))的切线不断逼近解;

任取一点(x0,f(x0)),其切线方程为 y=f'(x0)*(x-x0)+f(x0),其与x轴的交点为x1=x0-f(x0)/f'(x0),x1是一个比x0更接近的近似解;

依次类推,可以求出x2,x2又比x1更接近;

可以求出x3......

由此我们得出迭代公式为:x'=x-f(x)/f'(x),再带入f(x)=x*x-a得:x'=(x+a/x)/2;

代码:

 #include<bits/stdc++.h>
#define MAXN 100000+10
#define MAX 100000000
#define eps 1e-6
#define ll long long
using namespace std; float get_sqrt(float a)
{
float x, now;
x=a;
do
{
now=x; //**now保存上一次的x值
x=(x+a/x)/; //**通过迭代更新x的值使其接近解
}while(abs(now-x)>eps); //**两次计算的误差小于eps,x即为所求值
return x;
} int main(void)
{
std::ios::sync_with_stdio(false), cin.tie(), cin.tie();
float x;
cin >> x;
cout << get_sqrt(x) << endl;
return ;
}

其效率较之二分高了很多,不过还是不如库函数;

神代码(效率为库函数的4倍):

 #include<bits/stdc++.h>
#define MAXN 100000+10
#define MAX 100000000
#define eps 1e-6
#define ll long long
using namespace std; /*float InvSqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed //**可以通过减少迭代次数来用精度换取时间
#ifndef Q3_VM
#ifdef __linux__
assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
return 1/y;
}*/ float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (i>>); // 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 /x;
} int main(void)
{
std::ios::sync_with_stdio(false), cin.tie(), cin.tie();
float x;
cin >> x;
cout << InvSqrt(x) << endl;
return ;
}

其本质还是迭代法,不过因为那个魔鬼般的常数0x5f375a86 和 i = 0x5f375a86- (i>>1);中的位运算大大提高了其速度;

然而我并没有看懂,待以后继续研究;

求sqrt()底层效率问题(二分/牛顿迭代)的更多相关文章

  1. HDU.2899.Strange fuction(牛顿迭代)

    题目链接 \(Description\) 求函数\(F(x)=6\times x^7+8\times x^6+7\times x^3+5\times x^2-y\times x\)在\(x\in \l ...

  2. 二分法和牛顿迭代实现开根号函数:OC的实现

    最近有人贴出BAT的面试题,题目链接. 就是实现系统的开根号的操作,并且要求一定的误差,其实这类题就是两种方法,二分法和牛顿迭代,现在用OC的方法实现如下: 第一:二分法实现 -(double)sqr ...

  3. 牛顿迭代,多项式求逆,除法,开方,exp,ln,求幂

    牛顿迭代 若 \[G(F_0(x))\equiv 0(mod\ x^{2^t})\] 牛顿迭代 \[F(x)\equiv F_0(x)-\frac{G(F_0(x))}{G'(F_0(x))}(mod ...

  4. 已知 sqrt (2)约等于 1.414,要求不用数学库,求 sqrt (2)精确到小数点后 10 位

    问题:已知 sqrt (2)约等于 1.414,要求不用数学库,求 sqrt (2)精确到小数点后 10 位. 出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家. 考察点:基础算法的灵活应 ...

  5. Codevs 1038 一元三次方程求解 NOIP 2001(导数 牛顿迭代)

    1038 一元三次方程求解 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 有形如:ax3+b ...

  6. Poj 2976 Dropping tests(01分数规划 牛顿迭代)

    Dropping tests Time Limit: 1000MS Memory Limit: 65536K Description In a certain course, you take n t ...

  7. 【leetcode】【二分 | 牛顿迭代法】69_Sqrt(x)

    题目链接:传送门 题目描述: 求Sqrt(x),返回整数值即可. [代码]: #include<bits/stdc++.h> using namespace std; ; /* int m ...

  8. 【XSY2680】玩具谜题 NTT 牛顿迭代

    题目描述 小南一共有\(n\)种不同的玩具小人,每种玩具小人的数量都可以被认为是无限大.每种玩具小人都有特定的血量,第\(i\)种玩具小人的血量就是整数\(i\).此外,每种玩具小人还有自己的攻击力, ...

  9. 【loj6538】烷基计数 加强版 加强版 Burnside引理+多项式牛顿迭代

    别问我为啥突然刷了道OI题,也别问我为啥花括号不换行了... 题目描述 求含 $n$ 个碳原子的本质不同的烷基数目模 $998244353$ 的结果.$1\le n\le 10^5$ . 题解 Bur ...

随机推荐

  1. android Activity基类通用方法

    public class BaseActivity extends Activity { Resources res; // 通用资源缩写 @Override protected void onCre ...

  2. Java多线程基础知识(四)

    一. Condition 接口 1. Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式. 但是这两者在使用方式以及功能特性上还是有差别的. 2. 支持多 ...

  3. HDU 3351 Seinfeld(括号匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3351 解题报告:输入一个只有'{'跟'}'的字符串,有两种操作,一种是把'{'变成'}',另一种是'} ...

  4. BZOJ3223——Tyvj 1729 文艺平衡树

    1.题目大意:维护序列,只有区间翻转这个操作 2.分析:splay的经典操作就是实现区间翻转,就是在splay中有一个标记,表示这个区间被翻转了 然后就是记得各种的操作访问某个点时,记得下传,顺便交换 ...

  5. 通过Unity3d创建二维码(利用zxing2.2)

    http://blog.csdn.net/liulala16/article/details/14521979 2013-11-08 14:53 1965人阅读 评论(3) 收藏 举报 首先 下载ZX ...

  6. mysql 同步

    http://dev.mysql.com/doc/refman/5.5/en/replication-howto.html http://blog.csdn.net/mycwq/article/det ...

  7. git 使用入门篇

    最近准备给同事培训git,发现了一个不错的资源,在这里:http://www.gitguys.com/topics/creating-a-shared-repository-users-sharing ...

  8. 转:理解Cookie和Session机制

    原文: 理解Cookie和Session机制 摘要: Cookie工作原理 由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份.怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论 ...

  9. mysql中,主键与普通索引

    一.什么是索引?索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里 ...

  10. 《oracle每日一练》oracle截取字符的函数

    转载 在Oracle中 可以使用instr函数对某个字符串进行判断,判断其是否含有指定的字符. 在一个字符串中查找指定的字符,返回被查找到的指定的字符的位置. 语法: instr(sourceStri ...