【问题标题】:Is the Carmack/Welsh inverse square root algorithm biasedCarmack/Welsh 逆平方根算法是否有偏见
【发布时间】: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。
  • 啊,好吧 - 那么我没有更多要补充的了......而且我不确定类型双关语是否“安全” - 你在编译器的手中做正确的事情- 有人在另一个帖子中说“你在任何时候都只能有一个活跃的成员在一个工会中”,所以通过工会的类型双关语似乎也被关闭了 - 或者我误解了那个评论。

标签: c algorithm math


【解决方案1】:

牛顿法会产生偏差。求零的函数,

f(y) = x - 1/y²

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

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

所以是的,存在偏差,添加少量通常会改善结果。但不总是。例如,在 1.25 或 0.85 附近的区域,没有调整的结果要好于有调整的结果。在其他地区,调整会产生一点点额外的精度,在其他地区会更多。

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

【讨论】:

    【解决方案2】:

    由于此方法是一种近似值,因此结果有时会被高估,而另一些则被低估。您可以在 McEniry's paper 上找到一些关于此错误如何针对不同配置分布的漂亮数据,以及它们背后的数学原理。

    因此,除非您有确凿的证据证明在您的应用领域中结果明显有偏差,否则我更愿意按照Lomont's document 中的建议调整魔法常数 :-)

    【讨论】:

    • +1。真的很喜欢 Lomont 对 0x5f375a86 常量的分析。
    • 实际上,使用 0x5f3759df 和 0x5f375a86 我得到完全相同的偏差。
    • 好的,我坚持我所说的:如果您知道在您的特定应用领域存在偏见,您可以补偿它。丹尼尔费舍尔的回答很清楚^_^​​
    猜你喜欢
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2011-05-04
    相关资源
    最近更新 更多