【发布时间】:2013-02-07 10:32:40
【问题描述】:
在实施"Carmack's Inverse Square Root" algorithm 时,我注意到结果似乎有偏差。下面的代码似乎给出了更好的结果:
float InvSqrtF(float x)
{
// Initial approximation by Greg Walsh.
int i = * ( int* ) &x;
i = 0x5f3759df - ( i >> 1 );
float y = * ( float * ) &i;
// Two iterations of Newton-Raphson's method to refine the initial estimate.
x *= 0.5f;
float f = 1.5F;
y = y * ( f - ( x * y * y ) );
y = y * ( f - ( x * y * y ) );
* ( int * )(&y) += 0x13; // More magic.
return y;
}
关键区别在于倒数第二个“更神奇”的行。由于初始结果因一个相当恒定的因素而太低,因此只需一条指令即可将 19 * 2^(exponent(y)-bias) 添加到结果中。它似乎给了我大约 3 个额外的位,但我是否忽略了什么?
【问题讨论】:
-
您的问题到底是什么? “19 是正确的数字吗?”还是别的什么?
-
这段代码难道不是被严格的别名规则注定了未定义的行为吗?
-
@comocomocomocomo 您可以安全地使用 union 键入双关语。
-
@MatsPetersson:不知道,目标是 ARM。
-
啊,好吧 - 那么我没有更多要补充的了......而且我不确定类型双关语是否“安全” - 你在编译器的手中做正确的事情- 有人在另一个帖子中说“你在任何时候都只能有一个活跃的成员在一个工会中”,所以通过工会的类型双关语似乎也被关闭了 - 或者我误解了那个评论。