[Go] Fast Inverse Square Root

程式語言:Go
Package:
math

功能:快速計算出平方根的倒數

程式碼

Playground
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "math"
  6. )
  7.  
  8. func InvSqrt(x float32) float32 {
  9. var xhalf float32
  10. xhalf = 0.5 * x
  11. i := math.Float32bits(x)
  12. i = 0x5f3759df - (i >> 1) // 證明如下,直接求得接近的值
  13. x = math.Float32frombits(i)
  14. x = x * (1.5 - xhalf*x*x) // 牛頓-拉弗森方法
  15.  
  16. return x
  17. }
  18.  
  19. func main() {
  20. fmt.Println(InvSqrt(4))
  21. }
牛頓-拉弗森方法
0=(xx0)f(x0)+f(x0)xn+1=xnf(xn)f(xn)

證明

單精度浮點數的定義下
x=(1)s2e127(1+m)=(1)s2e(1+m) 開根號,故只看正浮點數,s=0,且將對應的 4 bytes 轉成整數來看的話
X=EL+ME=e+127=E+BM=m223=mL log2 x=log2[2e(1+m)]=e+log2(1+m)e+m+δ 最大 δ=0.04504656791687011719
log2 xe+m+δe=EB,m=ML=EB+ML+δ=EL+ML(Bδ)X=EL+M=XL(Bδ) 可得
log2 xXL(Bδ)(1)
x=1xlog2 x=12log2 x 代入(1)
XL(Bδ)=12(XL(Bδ))XL=12XL+32(Bδ)X=12X+32L(Bδ)X=32L(Bδ)12XL=223,B=127,δ=0.04504656791687011719 的值代入,可得證
i = 0x5f3759df - (i >> 1) 
依此想法,可推廣至其他的數學運算,快速求一解
像是立方根、平方根、倒數立方根等…
L=223,B=127,s=0 可能需再調整,此處的條件為 32-bit 的單精度浮點數,求平方根倒數

參考

0x5f3759df 这个快速开方中的常数的数学依据和原理
FAST INVERSE SQUARE ROOT
如何通俗易懂地讲解牛顿迭代法?

留言