Carmack/Welsh平方根逆算法是否有偏差

Carmack/Welsh平方根逆算法是否有偏差,c,algorithm,math,C,Algorithm,Math,在实施时,我注意到结果似乎有偏差。以下代码似乎给出了更好的结果: 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-Raphso

在实施时,我注意到结果似乎有偏差。以下代码似乎给出了更好的结果:

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^(指数(y)-偏差)。它似乎给了我大约3个额外的位,但我忽略了什么吗?

由于这种方法是一种近似方法,结果有时会被高估,有时会被低估。您可以在一些漂亮的数字上找到这个错误是如何在不同配置下分布的,以及它们背后的数学原理


因此,除非你有确凿的证据证明在你的应用领域中,结果明显有偏差,否则我更倾向于调整魔术常数,如:-)

牛顿的方法产生偏差。要查找其零点的函数

f(y) = x - 1/y²
是凹的,所以-除非你从y开始≥ √(3/x)-牛顿法只产生近似值
≤ 1/√x
(并且严格更小,除非从精确的结果开始)

浮点运算偶尔会产生过大的近似值,但通常不会在前两次迭代中产生(因为初始猜测通常不够接近)

因此,是的,存在偏差,添加少量通常会改善结果。但并非总是如此。例如,在1.25或0.85左右的区域内,未经调整的结果优于未经调整的结果。在其他地区,调整会产生一点额外的精度,而在其他地区则会产生更多的精度


在任何情况下,要添加的魔法常数都应该调整到最常用的
x
区域,以获得最佳结果。

您的问题是什么?“添加19是正确的数字吗?”还是其他什么?根据严格的别名规则,这段代码不是注定会有未定义的行为吗?@como你可以用一个联合来安全地键入双关语。@Matstpeterson:不知道,目标是ARM。啊,好的-那么我没有更多的补充了。。。我不确定类型双关是否“安全”——你在编译器手中做正确的事情——有人在另一个帖子中说“你在任何时候都只能有一个联盟中的活跃成员”,所以通过联盟的类型双关似乎也被关闭了——或者我误解了这个评论。就像Lomont对
0x5f375a86
常数的分析一样。实际上,对于0x5f3759df和0x5f375a86,我得到了完全相同的偏差。好吧,我坚持我说的:如果在你的特定应用领域中你知道存在偏差,你可以补偿它。丹尼尔·费舍尔的回答非常清楚^_^