#include<stdio.h>
#include<string.h>
#include <stdlib.h> /* atof */ /*
计算=1/sqrt(n)
*/
float Q_rsqrt( 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 y;
} int main(int argc, char const *argv[])
{
float f9 = 81.0f;
f9 = Q_rsqrt(f9); printf("f9=%f\n", f9); return 0;
}

  运行结果:

f9=0.111086

和计算机1/sqrt(81)很接近1/9=0.111111

相比 sqrt() 函数,这套算法要快将近4倍,要知道,编译器自带的函数,可是经过严格仔细的汇编优化的啊!

牛顿迭代法的原理是先猜测一个值,然后从这个值开始进行叠代。因此,猜测的值越准,叠代的次数越少。卡马克选了0x5f3759df这个值作为猜测的结果,再加上后面的移位算法,得到的y非常接近1/sqrt(n)。这样,我们只需要2次牛顿迭代法就可以达到我们所需要的精度。

函数返回1/sqrt(x),这个函数在图像处理中比sqrt(x)更有用。

注意到这个正数只用了一次叠代!(其实就是根本没用叠代,直接运算)。编译、实验,这个团数不仅工作的很好,而且比标准的sqrt()函数快4倍!

这个简洁的定数,最核心,也是最让人费解的,就是标注了what the fuck的一句 i   = 0x5f3759df - ( i >> 1 );再加上y   = y * ( threehalfs - ( x2 * y * y ) )。

两句话就完成了开方运算!而且注意到,核心那句是移位运算,速度极快!特别在很多没有乘法指令的RISC结构CPU上,这样做是极其高效的。

算法的原理就是使用牛顿迭代法,用 x-f(x)/f'(x) 来不断的逼近 f(x)=a 的根。

求平方根:f(x)=x^2=a ,f'(x)= 2*x, f(x)/f'(x)=x/2,把 f(x) 代入 x-f(x)/f'(x)后有(x+a/x)/2,

现在我们选 a=5,选一个猜测值比如 2,  那么我们可以这么算  5/2 = 2.5; (2.5+2)/2 = 2.25; 5/2.25 = ……  这样反复迭代下去,结果必定收敛于 sqrt(5)。

但是卡马克作者真正厉害的地方是他选择了一个神秘的常数 0x5f375a86来计算那个梦“值,

就是我们加注释的那一行那行算出的值非常接近1/sqrt(n)这样我们只需要2次牛顿迭代就可以达到我们所需要的精度。

快速开平方取倒数的算法--嵌入式ARM转载的更多相关文章

  1. 用C语言将一个数开根号后再取倒数的方法

    在上学的时候,曾经看过有人写过这样的算法,就是将一个数开根号后再取倒数的算法,我本人也觉得十分巧妙,于是就将它积累了下来,让我们来看看是怎么回事: #include <stdio.h> # ...

  2. HDU--杭电--4506--小明系列故事——师兄帮帮忙--快速幂取模

    小明系列故事——师兄帮帮忙 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) To ...

  3. 【转】C语言快速幂取模算法小结

    (转自:http://www.jb51.net/article/54947.htm) 本文实例汇总了C语言实现的快速幂取模算法,是比较常见的算法.分享给大家供大家参考之用.具体如下: 首先,所谓的快速 ...

  4. HDU 1061 Rightmost Digit --- 快速幂取模

    HDU 1061 题目大意:给定数字n(1<=n<=1,000,000,000),求n^n%10的结果 解题思路:首先n可以很大,直接累积n^n再求模肯定是不可取的, 因为会超出数据范围, ...

  5. Fast InvSqrt()(平方根倒数速算法)

    浮点数的平方根倒数常用于计算正规化矢量.3D图形程序需要使用正规化矢量来实现光照和投影效果,因此每秒都需要做上百万次平方根倒数运算,而在处理坐标转换与光源的专用硬件设备出现前,这些计算都由软件完成,计 ...

  6. Powmod快速幂取模

    快速幂取模算法详解 1.大数模幂运算的缺陷: 快速幂取模算法的引入是从大数的小数取模的朴素算法的局限性所提出的,在朴素的方法中我们计算一个数比如5^1003%31是非常消耗我们的计算资源的,在整个计算 ...

  7. 洛谷 P1226 【模板】快速幂||取余运算

    题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...

  8. 《Java语言实现快速幂取模》

    快速幂取模算法的引入是从大数的小数取模的朴素算法的局限性所提出的,在朴素的方法中我们计算一个数比如5^1003%31是非常消耗我们的计算资源的,在整个计算过程中最麻烦的就是我们的5^1003这个过程 ...

  9. 二分求幂/快速幂取模运算——root(N,k)

    二分求幂 int getMi(int a,int b) { ; ) { //当二进制位k位为1时,需要累乘a的2^k次方,然后用ans保存 == ) { ans *= a; } a *= a; b / ...

随机推荐

  1. LeetCode 566. 重塑矩阵(Reshape the Matrix)

    566. 重塑矩阵 566. Reshape the Matrix 题目描述 LeetCode LeetCode LeetCode566. Reshape the Matrix简单 Java 实现 c ...

  2. python使用matplotlib在一个图形中绘制多个子图以及一个子图中绘制多条动态折线问题

    在讲解绘制多个子图之前先简单了解一下使用matplotlib绘制一个图,导入绘图所需库matplotlib并创建一个等间隔的列表x,将[0,2*pi]等分为50等份,绘制函数sin(x).当没有给定x ...

  3. Windows的socket编程

    ################服务端 1.准备工作导入头文件 #include<WinSock2.h> #pragma comment(lib, "ws2_32.lib&quo ...

  4. nRF24L01/nRF24L01+应用总结

    nRF24L01+是nRF24L01的升级款,比较显眼的区别是nRF24L01+比nRF24L01多了一个250Kbps传输速率.其它的还有接收模式官方给的耗电量是不一样的.个别寄存器名字不一样. 接 ...

  5. 【LEETCODE】49、数组分类,简单级别,题目:566,1089

    package y2019.Algorithm.array; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.array * ...

  6. Dubbo快速入门 五

    5. Dubbo注解版 之前在dubbo配置文件显式编写内容提供者和消费者,官方还提供了了一种注解方式,接下来改造项目 1.服务提供方 dubbo配置文件 将之前手动申明注释掉,添加<dubbo ...

  7. Dubbo学习摘录(零)

    节点角色说明: Provider:暴露服务的服务提供方: Consumer:调用远程服务的服务消费方: Registry:服务注册与发现的注册中心: Monitor: 统计服务的调用次数和调用时间: ...

  8. ZFS文件系统及Freenas介绍

    一.简介 1.什么是zfs文件系统 ZFS文件系统的英文名称为Zettabyte File System,也叫动态文件系统(Dynamic File System),是第一个128位文件系统.最初是由 ...

  9. Zookeeper学习笔记(三)——java客户端代码操作

    Zookeeper客户端java代码操作 上篇博客记录了shell命令操作zookeeper集群的方式,这次尝试采用java代码来操作.通过查阅API,发现并不困难. 1. 首先获得客户端与服务器的连 ...

  10. 查看font字体文件

    url: http://bluejamesbond.github.io/CharacterMap/ 打开网址后,如下图操作