浮点平方根近似如何工作?

YSC:

我发现了一个相当奇怪但可工作的平方根近似值float我真的不明白。有人可以向我解释为什么此代码有效吗?

float sqrt(float f)
{
    const int result = 0x1fbb4000 + (*(int*)&f >> 1);
    return *(float*)&result;   
}

我已经对其进行了一点测试,它输出的值偏离std::sqrt()了大约1-3%我知道雷神之锤III的快速反平方根,我想这里有点类似(没有牛顿迭代),但是我真的很感谢对其工作原理的解释

(注意:我已经将其标记为因为它们都是有效的(请参见注释)C和C ++代码)

奥利弗·查尔斯沃斯(Oliver Charlesworth):

(*(int*)&f >> 1)将的按位表示形式右移f几乎将指数除以二,大约等于取平方根。1个

为什么差不多在IEEE-754中,实际指数为e-1272要将此除以二,我们需要e / 2-64,但是上述近似值仅给出e / 2-127因此,我们需要在结果指数上加上63。这是由该魔术常数(0x1fbb4000)的第30-23位贡献的

我以为魔术常数的其余位已被选择来最小化整个尾数范围内的最大误差,或者类似的东西。但是,尚不清楚它是通过分析,迭代还是启发式确定的。


值得指出的是,这种方法是不可移植的。它至少做出以下假设:

  • 该平台使用的单精度IEEE-754 float
  • float表示的字节序
  • 由于这种方法违反了C / C ++的严格混叠规则,因此您不会受到未定义行为的影响

因此,应该避免使用它,除非您确定它在您的平台上提供了可预测的行为(并且确实提供了有用的加速vs. sqrtf!)。


1. sqrt(a ^ b)=(a ^ b)^ 0.5 = a ^(b / 2)

2.参见例如https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Exponent_encoding

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章