求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 ...
随机推荐
- u-boot 2011.09 调用kernel 的流程
这段时候我总是觉得有个问题,u-boot 的存在是不是就是为了调用kernel 而存在的. 所以,粗浅的跟了一下这个流程,还有很多细节上的东西没有做好,往指正. u-boot-2011.9 调用内核代 ...
- 简单的哈希表实现 C语言
简单的哈希表实现 简单的哈希表实现 原理 哈希表和节点数据结构的定义 初始化和释放哈希表 哈希散列算法 辅助函数strDup 哈希表的插入和修改 哈希表中查找 哈希表元素的移除 哈希表打印 测试一下 ...
- web图片轮播实现
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- centos 终端 字体颜色
默认情况下,没有颜色. https://www.centos.org/docs/2/rhl-gsg-en-7.2/ls-color.html git也默认没有颜色,破解如下: git config - ...
- 【GoLang】GoLang map 非线程安全 & 并发度写优化
Catena (时序存储引擎)中有一个函数的实现备受争议,它从 map 中根据指定的 name 获取一个 metricSource.每一次插入操作都会至少调用一次这个函数,现实场景中该函数调用更是频繁 ...
- Redis提供的持久化机制(RDB和AOF)
Redis提供的持久化机制 Redis是一种面向"key-value"类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却 ...
- POJ 2352
---恢复内容开始--- http://poj.org/problem?id=2352 这是一个树状数组的题目,也是我第一次接触这类的题目,也正是因为之前的一道题,TLE了,超时太严重了,我看disc ...
- MySQL Got fatal error 1236原因和解决方法【转】
本文来自:http://blog.itpub.net/22664653/viewspace-1714269/ 一 前言 MySQL 的主从复制作为一项高可用特性,用于将主库的数据同步到从库,在维护主 ...
- FFmpeg-20160415-snapshot-bin
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 F ...
- Spring配置数据源
Spring在第三方依赖包中包含了两个数据源的实现类包,其一是Apache的DBCP,其二是 C3P0.可以在Spring配置文件中利用这两者中任何一个配置数据源. DBCP数据源 DBCP类包位于 ...