代码

背景

第一眼看代码我们可以get到这个函数需要输入一个浮点数,输出一个浮点数,那我们接下来先拆解下这个输入输出的秘密。首先,我们知道一个单位向量的公式。

出于计算机硬件设计的历史原因,硬件除法指令和开方的实现性能较差,你可以查看intel的指令手册关于latency的数据。那我们可以从软件层规避掉这种指令吗?答案是可以的,我们接下来看看id software的工程师是如何处理这个问题的。

那么我们还需要找到一个近似函数也就是Q_rsqrt替代

到这里我们输入输出就搞明白了,输入是,输出是

注释1: evil floating point bit level hacking

因为我们不能在浮点数上进行位运算的操作,我们先将float转成int。

可以看看下面quake 2 engine的一个函数Q_fabs(float absolute)。

注释2: what the fuck

第一步转换成函数等式消除除法指令。

我们需要找到一个的近似替换函数,但首先先看看如何利用二进制的数据计算浮点数,例如浮点数,我们利用十进制转二进制计算器(包含对应计算的算法步骤)转换成二进制的形式:

标准化该二进制数字,用任意base转换公式计算十进制数值。

然后得到浮点数的计算公式

比方说上述的,就可以写为。

转换公式(2)为方程。

,出于某种原因是该算法的最优参数。

该公式可以近似替换为。

然后第二步我们将float类型二进制转换为int类型数值,首先先看一下float的二进制格式。

590px-Float_w_significand_2.svg

根据浮点数编码的定义

例如相对应的值为,可以用这个在线的浮点数转换网站验证我们的结果。

于是我们可以得到如何解析浮点数二进制转换成整数的公式。

根据公式(3)得。

可以看到的plot曲线是很近似的。

Log_by_aliasing_to_int

带入公式(1)得。

因为是常量,于是我们可以得到代码里的"magic number"。

注释3: 1st iteration

Newton's method

比如说

带入公式(4)。

回到

带入公式(4)。

源代码的实现。

最后

wiki有一篇很棒的文章关于这个算法实现,以及讲述科学计数法和浮点数编解码是如何相关联的一篇blog,祝阅读愉快。