Quake III 1999

平方根倒数速算法

一行位运算黑魔法,把 1/√x 的计算加速近 4 倍。拖动滑块,逐比特看它如何施展魔法。

速算挑战

拖动滑块或点击预设值,实时对比标准计算与速算结果。

x = 2.00
精确输入
标准计算 1/√x
0.707107
Math.sqrt
速算结果
0.706930
位运算 + 牛顿迭代
相对误差
0.0250%
excellent

逐比特分解

点击「播放」逐步查看 32 位浮点数如何被位运算一步步变换为 1/√x。

0 / 5
Step 0 输入浮点数 x
将 x 存入 32 位浮点寄存器
符号 1bit 指数 8bit 尾数 23bit
浮点值
2.000000
整数
1073741824
十六进制
0x40000000

牛顿迭代的威力

位运算给出粗略近似,一次牛顿迭代让误差骤降一个数量级。

牛顿迭代公式
y = y × (1.5 − 0.5 × x × y²)

牛顿-拉弗森法利用当前点的切线逼近零点。对于 1/√x,迭代以平方速度收敛--一次迭代误差降到 0.2% 以内,两次接近机器精度。

全局精度扫描

在 0.01 ~ 1000 范围内采样,切换迭代次数对比误差分布。

魔法常数探秘

如果不用 0x5f3759df,换个常数会怎样?输入试试,或在图表上拖动看附近常数的表现。

纵轴为各常数在 0.001~1000 范围内的最大误差。红线标示 Quake III 原始常数 0x5f3759df。

为什么这能行?

01

IEEE 754 的巧合

32 位浮点数的指数段恰好近似 log₂(x) 的整数部分。右移一位 ≈ 指数除以 2 ≈ 开平方。尾数段也近似对数的小数部分,使整体位模式接近 log₂(x)。

02

对数域线性近似

1/√x = x^(−0.5),取对数后是 −0.5 × log₂(x)。整数右移一位完成 ÷2,魔法常数修正偏差并取反符号,一步搞定对数域的缩放与取反。

03

牛顿迭代收尾

位运算给出 4% 以内的初始近似。牛顿法以平方速度收敛--一次迭代误差降到 0.2% 以内,两次接近机器精度。这就是为什么只需要一次迭代。

传奇起源

这段代码最早出现在 1999 年 Quake III Arena 源码的 q_math.c 文件中,函数名 Q_rsqrt。原始注释写着「what the fuck?」。魔法常数 0x5f3759df 的最优值由数学家 Chris Lomont 在 2003 年严格推导验证,他找到的理论最优值 0x5f37642f 与原版几乎一致。后来 Gary Tarolli 透露这是 SGI 工作站时代逐步调优的经验值,不是一人之功。

现在还需要吗?

现代 CPU 有了 rsqrtss 等硬件指令,一条指令就能完成近似平方根倒数,比这个算法还快。但这段代码的意义不在于速度--它是对浮点数底层结构的深刻洞察,是「把数据的不同解释玩出花来」的经典案例。理解它,你就理解了计算机如何真正存储和处理数字。