求sqrt()底层效率问题(二分/牛顿迭代)
偶然看见一段求根的神代码,于是就有了这篇博客;
对于求根问题,通常我们可以调用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()底层效率问题(二分/牛顿迭代)的更多相关文章
- 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 ...
 - 二分法和牛顿迭代实现开根号函数:OC的实现
		
最近有人贴出BAT的面试题,题目链接. 就是实现系统的开根号的操作,并且要求一定的误差,其实这类题就是两种方法,二分法和牛顿迭代,现在用OC的方法实现如下: 第一:二分法实现 -(double)sqr ...
 - 牛顿迭代,多项式求逆,除法,开方,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 ...
 - 已知 sqrt (2)约等于 1.414,要求不用数学库,求 sqrt (2)精确到小数点后 10 位
		
问题:已知 sqrt (2)约等于 1.414,要求不用数学库,求 sqrt (2)精确到小数点后 10 位. 出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家. 考察点:基础算法的灵活应 ...
 - Codevs 1038 一元三次方程求解 NOIP 2001(导数 牛顿迭代)
		
1038 一元三次方程求解 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 有形如:ax3+b ...
 - Poj 2976 Dropping tests(01分数规划 牛顿迭代)
		
Dropping tests Time Limit: 1000MS Memory Limit: 65536K Description In a certain course, you take n t ...
 - 【leetcode】【二分 | 牛顿迭代法】69_Sqrt(x)
		
题目链接:传送门 题目描述: 求Sqrt(x),返回整数值即可. [代码]: #include<bits/stdc++.h> using namespace std; ; /* int m ...
 - 【XSY2680】玩具谜题 NTT 牛顿迭代
		
题目描述 小南一共有\(n\)种不同的玩具小人,每种玩具小人的数量都可以被认为是无限大.每种玩具小人都有特定的血量,第\(i\)种玩具小人的血量就是整数\(i\).此外,每种玩具小人还有自己的攻击力, ...
 - 【loj6538】烷基计数 加强版 加强版 Burnside引理+多项式牛顿迭代
		
别问我为啥突然刷了道OI题,也别问我为啥花括号不换行了... 题目描述 求含 $n$ 个碳原子的本质不同的烷基数目模 $998244353$ 的结果.$1\le n\le 10^5$ . 题解 Bur ...
 
随机推荐
- CSS DIV HOVER
			
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
 - BZOJ3196——二逼平衡树
			
1.题目大意:给你一个序列,有5种操作,都有什么呢... 1> 区间第k小 这个直接用二分+树套树做 2> 区间小于k的有多少 这个直接用树套树做 3> 单点修改 这个直接用树套树做 ...
 - 跟着百度学PHP[4]OOP面对对象编程-4-对象成员的访问 ->
			
使用一个减号一个尖括号->来达到访问对象成员. $object->方法 来看案例. <?php class Person{ private $name; "; var $s ...
 - Java对文件中的对象进行存取
			
1.保存对象到文件中 Java语言只能将实现了Serializable接口的类的对象保存到文件中,利用如下方法即可: public static void writeObjectToFile(Obje ...
 - SQL 多表一起查询的语句总结
			
sql 同时查询多个表 可以使用连表查询比如使用join sql 同时查询多个表 可以使用连表查询 比如 使用join select s1.*,s2.* from s1 left join s2 on ...
 - echarts之字符云tooltip显示混乱问题的解决办法
			
echarts字符云中tooltip显示混乱主要表现为一下两点: 1.字体与其显示框内容不对应鼠标识别错误 解决思路: 就是option里的数据要对value降序排序(这一点很关键,是必须的一步) 把 ...
 - ajax初探01
			
1.为什么使用ajax ajax使用异步处理模型,意味着在浏览器等待数据加载期间,用户可以做其他事情 在页面正在加载时使用ajax:使用ajax,浏览器可以向服务器请求一些数据,并且一旦数据请求发出, ...
 - 数据库多对多关联表(Python&MySQL)
			
Python Python对MySQL数据库操作使用的是sqlalchemy这个ORM框架 #一本书可以有多个作者,一个作者又可以出版多本书 from sqlalchemy import Table, ...
 - Java BigDecimal使用
			
//除法:精确到后4位BigDecimal a = new BigDecimal(1213); BigDecimal b = new BigDecimal(10302); BigDecimal rat ...
 - iOS 利用不等的constraint实现布局间隔调整
			
以前也写过一篇文章,说的也是如何利用constraint调整布局间隔,今天说另一种方法,实现简单,但有一定局限. 先看图 这里只截取了一部分,这个页面在4寸是可以显示的,但是如果不把控件间的间距缩小, ...