平方根联合与位移

库珀·詹姆斯

我发现获得了平方根的这段代码使我吃惊的是它的方式,使用并集和位移位是下面的代码:

float sqrt3(const float x)  
{
  union
  {
    int i;
    float x;
  } u;

  u.x = x;
  u.i = (1<<29) + (u.i >> 1) - (1<<22); 
  return u.x;
} 

首先将x的值保存在ux,然后为ui分配一个值,然后将该数字的平方根神奇地显示为ux

??有人向我解释该算法如何?

Iwillnotexist Idonotexist

上面的代码展示了UB(未定义的行为),因此不应信任它可以在任何平台上工作。这是因为它写入a的成员,union并从与其上次使用unionwith写入的成员不同的成员进行回读它还在很大程度上取决于字节顺序(多字节整数内的字节顺序)。

但是,它通常会完成预期的工作,并了解为什么值得阅读有关IEEE 754 binary32浮点格式的信息

IEEE754 binary32格式的速成班

IEEE754通常将32位浮点数划分为1个符号位,8个指数位和23个尾数位,从而得出

                   31 30-23           22-0
Bit#:               ||------||---------------------|
Bit Representation: seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
Value:              sign * 1.mantissa * pow(2, exponent-127)

该数字基本上以“科学计数法,以2为底”。

详细而言,指数以“有偏”形式存储(即,其值太高127个单位)。这就是为什么我们从编码指数中减去127以获得“真实”指数的原因。

简短说明

您代码的作用是指数部分减半并损坏尾数这样做是因为数的平方根的指数大约为一半

以10为底的示例

假设我们想要4000000 = 4 * 10 ^ 6的平方根。

4000000 ~ 4*10^6  <- Exponent is 6
4000    ~ 4*10^3  <- Divide exponent in half

只需将指数6除以2,得到3,然后将其设为新指数,我们就已经处于正确的数量级之内,并且更接近于事实,

2000 = sqrt(4000000)

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章