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

对于求根问题,通常我们可以调用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. 利用Jquery的load函数实现页面的动态加载

    利用Jquery的load函数实现页面的动态加载  js的强大功能相信大家都知晓,今天通过jquery的库函数load可以更加方便的实现页面的动态刷新,经过几天的研究与探索,终于有所成效!吾心甚蔚! ...

  2. CentOS 6.5 安装nginx 1.6.3

    使用epel [root@nginx /]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo ...

  3. 基于jQuery的对象切换插件:soChange 1.5 (点击下载)

    http://www.jsfoot.com/jquery/demo/2011-09-20/192.html 所有参数: $(obj).soChange({     thumbObj:null, //导 ...

  4. linux 下 修改mysql账号密码

    1.root用户登录到mysql数据库代码示例:/usr/local/mysql/bin/mysql -u root -p (输入密码进入mysql)2.进入mysql,输入:代码示例:use mys ...

  5. mongodb 释放磁盘空间

    db.copyDatabase("from","to","127.0.0.1:16161"); 将127.0.0.1上的from库.拷贝到t ...

  6. iOS开发——UI基础-屏幕适配

    一.适配 1.什么是适配?适应.兼容各种不同的情况 2.移动开发中,适配的常见种类 2.1系统适配 针对不同版本的操作系统进行适配 2.2屏幕适配 针对不同大小的屏幕尺寸进行适配 二.点和像素 1.在 ...

  7. iOS 图片 的 聊天气泡显示 Objective-C

    - (void)viewDidLoad { [super viewDidLoad]; UIImageView *ImageView01 = [[UIImageView alloc] init]; [I ...

  8. 简述JavaScript的运行机制

    想要理解JavaScript的运行机制,需要分别深刻理解以下几个点: · JavaScript的单线程机制 · 任务队列(同步任务和异步任务) · 事件和回调函数 · 定时器 · Event Loop ...

  9. 2015校招网易C/C++工程师笔试题(附答案)

    1. #include < filename.h >和#i nclude “filename.h” 有什么区别?   答:对于#i nclude < filename.h >, ...

  10. Linux system 函数的一些注意事项

    在日常的代码编程中 , 我们可以利用system  函数去调用一些我们自己想调用的命令 , 并获取他的返回值. 函数的原型如下: int system(const char *command); 上一 ...