好的,到目前为止,我想很多人都知道着名的fast inverse square root(请参阅Writing your own square root function和0x5f3759df上的详情)
这是代码
float FastInvSqrt(float x) {
float xhalf = 0.5f * x;
int i = *(int*)&x; // evil floating point bit level hacking
i = 0x5f3759df - (i >> 1); // what the fuck?
x = *(float*)&i;
x = x*(1.5f-(xhalf*x*x)); // one Newton Method iteration
return x;
}
好的,我不需要知道更多魔法0x5f3759df
。
我不明白为什么x*(1.5f-(xhalf*x*x))
是Newton Method
次迭代?
我试过分析,但却无法得到它。
因此,假设r是实数,x是r的倒数sqrt。
1 / (x^2) = r
,然后是f(x) = r*(x^2)-1
和f'(x) = 2 * r * x
所以一次迭代应该是x1 = x - f(x)/f'(x) = x / 2 + 1 / (2 * r * x)
,对吗?
x * (1.5 - ((r / 2) * x * x))
怎么来?(注意我在这里用xhalf
替换了r / 2
修改
好的f(x) = x^2 - 1/r
是另一种形式,让我计算
f(x) = x^2 - 1 / r
f'(x) = 2 * x
所以x1 = x - (f(x)/f'(x)) = x - (x^2 -(1 / r))/(2*x) = x / 2 + 1 / (2 * r * x)
,它仍然与代码中使用的公式完全不同,对吗?
答案 0 :(得分:6)
维基百科说功能是(使用您的变量名称):
f(x)= 1 / x 2 - r
然后我们有:
f'(x)= -2 / x 3
迭代是:
x - f(x)/ f'(x)=
x - (1 / x 2 - r)/( - 2 / x 3 )=
x + x 3 / 2 *(1 / x 2 - r)=
x + x / 2 - r / 2 * x 3 =
x *(1.5 - r / 2 * x * x)
这就是你在代码中看到的。
答案 1 :(得分:3)
Newton's method是根据迭代定义的
x i + 1 = x i - f(x i )/ f'(x i )
(其中f'(x)是f(x)的一阶导数)。要找到r的反向根,需要找到函数f(x)= x - 1 / sqrt(r)的零(或等效地,f(x)= x 2 - 1 / R)。只需获取衍生物,将其插入到迭代步骤的定义中,简化并获得答案。
实际上,代码中使用的确切形式来自于使用第三种等效形式:
f(x)= x -2 - r
有关推导的详细步骤,请参阅this article。它也来自Wikipedia article on fast inverse square root。