《雷神之锤III》平方根倒数算法 学习笔记

今天刷到个算法视频,觉得很有意思,所以打算把它记录下来。

源代码

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 float point bit hack
	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, can be removed
	return y;
}

二进制浮点数运算

  • 参考标准 IEEE 754

  • 计算机中 小数(浮点数)表示 由三部分二进制组成 : S 符号位 sign, E 指数偏移值 exponent bias, M 尾数位 Mantissa。以32为 浮点数 float 为例:

    • 1位 符号位,8位指数位,23位有效数字位32位浮点float
    • E ∈ ( − 127 , 128 ] ,   M ∈ [ 0 , 2 23 − 1 ] E \in (-127, 128], \ M\in[0, 2^{23}-1] E(127,128], M[0,2231]
    • 其表示值 Value V 32 = S × 2 E − 127 × ( 1 + 1 2 23 M ) \begin{aligned}V_{32} &= S \times 2^{E - 127} \times (1 + \frac{1}{2^{23}}M) \end{aligned} V32=S×2E127×(1+2231M)
  • 拓展延伸

    • 双精度 浮点数 double64位浮点double

      V 64 = S × 2 E − 1023 × ( 1 + 1 2 51 M ) \begin{aligned}V_{64} &= S \times 2^{E - 1023} \times (1 + \frac{1}{2^{51}}M) \end{aligned} V64=S×2E1023×(1+2511M)

    • 尾数位(Mantissa),它的取值范围为 1 ~ 2 ,或者为 0~1。它也被称为分数值(fraction)、系数位(Coefficient),有效数字位(Significand)。

    • 特殊数值:

      • 0 : 0 00000000 0000000000000000000000
        0 : 1 00000000 0000000000000000000000
      • NaN:
        • 指数位所有位都是1, 小数位只要不全为0,就表示非数值
        • 例:0 11111111 11111111111100000010000
      • Infinity:
        • 符号位 0表示正无穷大,1表示负无穷大;
        • 指数位 所有位都是1;
        • 小数位所有位都是0。
        • 例:0 11111111 00000000000000000000000
类别正负号实际指数有偏移指数指数域尾数域数值
0-12700000 0000000 0000 0000 0000 0000 00000.0
负零1-12700000 0000000 0000 0000 0000 0000 0000−0.0
1001270111 1111000 0000 0000 0000 0000 00001.0
-1101270111 1111000 0000 0000 0000 0000 0000−1.0
最小的非规约数*-12700000 0000000 0000 0000 0000 0000 0001±2× 2= ±2≈ ±1.4×10
中间大小的非规约数*-12700000 0000100 0000 0000 0000 0000 0000±2× 2= ±2≈ ±5.88×10
最大的非规约数*-12700000 0000111 1111 1111 1111 1111 1111±(1−2) × 2≈ ±1.18×10
最小的规约数*-12610000 0001000 0000 0000 0000 0000 0000±2≈ ±1.18×10
最大的规约数*1272541111 1110111 1111 1111 1111 1111 1111±(2−2) × 2≈ ±3.4×10
正无穷01282551111 1111000 0000 0000 0000 0000 0000+∞
负无穷11282551111 1111000 0000 0000 0000 0000 0000−∞
NaN*1282551111 1111non zeroNaN

对数技巧

  • 因为 平方根底数 为 正 S = + 1 S = +1 S=+1
  • log ⁡ 2 ( V 32 ) = log ⁡ 2 ( 2 E − 127 × ( 1 + 1 2 23 M ) ) = E − 127 + log ⁡ 2 ( 1 + 1 2 23 M ) ≈ E − 127 + 1 2 23 M + μ   ,   log ⁡ 2 ( 1 + x ) ≈ x + μ ≈ 1 2 23 ( M + 2 23 × E ) + μ − 127 \begin{aligned} \log_2 ( V_{32}) &= \log_2 \Big( 2^{E - 127} \times (1 + \frac{1}{2^{23}}M)\Big) \\ &= E - 127 + \log_2 (1 + \frac{1}{2^{23}}M) \\ &\approx E - 127 + \frac{1}{2^{23}}M + \mu \ , \ \log_2 (1+x) \approx x + \mu \\ & \approx \frac{1}{2^{23}}(M + 2^{23}\times E) + \mu - 127 \end{aligned} log2(V32)=log2(2E127×(1+2231M))=E127+log2(1+2231M)E127+2231M+μ , log2(1+x)x+μ2231(M+223×E)+μ127
  • M + 2 23 × E = M + ( E < < 23 ) = M + 2^{23} \times E = M + (E << 23) = M+223×E=M+(E<<23)= (binary) V 32 V_{32} V32

平方根倒数

  • 1 x = x − 1 2 \frac{1}{\sqrt{x}} = x ^{-\frac{1}{2}} x 1=x21
  • log ⁡ 2 ( 1 y ) = − 1 2 log ⁡ 2 ( y ) = − ( log ⁡ 2 ( y ) > > 1 ) \log_2(\frac{1}{\sqrt{y}}) = -\frac{1}{2} \log_2(y) = -(\log_2(y)>>1) log2(y 1)=21log2(y)=(log2(y)>>1)
  • Let log ⁡ ( Γ ) = − 1 2 log ⁡ ( y ) \log(\Gamma) = -\frac{1}{2} \log(y) log(Γ)=21log(y)
  • 1 2 23 ( M Γ + 2 23 × E Γ ) + μ − 127 = − 1 2 ( 1 2 23 ( M y + 2 23 × E y ) + μ − 127 ) ( M Γ + 2 23 × E Γ ) = 3 2 2 23 ( 127 − μ ) − 1 2 ( M y + 2 23 × E y ) = 0x5f3759df − ( y > > 1 ) \begin{aligned} \frac{1}{2^{23}}(M_\Gamma + 2^{23}\times E_\Gamma) + \mu - 127 &= -\frac{1}{2} (\frac{1}{2^{23}}(M_y + 2^{23}\times E_y) + \mu - 127) \\ (M_\Gamma + 2^{23}\times E_\Gamma) &= \frac{3}{2} 2^{23}(127 - \mu) - \frac{1}{2} (M_y + 2^{23}\times E_y) \\ &= \text{0x5f3759df} - (y >> 1) \end{aligned} 2231(MΓ+223×EΓ)+μ127(MΓ+223×EΓ)=21(2231(My+223×Ey)+μ127)=23223(127μ)21(My+223×Ey)=0x5f3759df(y>>1)
  • 再把二进制整数 转换成浮点数,结果为近似值,需要用牛顿迭代减少误差。

牛顿迭代

y = 1 x → x = 1 y 2 y = \frac{1}{\sqrt{x}} \to x = \frac{1}{y^2} y=x 1x=y21
f ( y ) = 1 y 2 − x f(y)=\frac{1}{y^{2}}-x f(y)=y21x
y new  = y − f ( y ) f ′ ( y ) = y − 1 y 2 − x − 2 y 3 = 3 2 y − 1 2 x y 3 y_{\text {new }}=y-\frac{f(y)}{f^{\prime}(y)}=y-\frac{\frac{1}{y^{2}}-x}{-\frac{2}{y^{3}}}=\frac{3}{2}y-\frac{1}{2} x y^{3} ynew =yf(y)f(y)=yy32y21x=23y21xy3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值