我发现获得了平方根的这段代码使我吃惊的是它的方式,使用并集和位移位是下面的代码:
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
??有人向我解释该算法如何?
上面的代码展示了UB(未定义的行为),因此不应信任它可以在任何平台上工作。这是因为它写入a的成员,union
并从与其上次使用union
with写入的成员不同的成员进行回读。它还在很大程度上取决于字节顺序(多字节整数内的字节顺序)。
但是,它通常会完成预期的工作,并了解为什么值得阅读有关IEEE 754 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以获得“真实”指数的原因。
您代码的作用是将指数部分减半并损坏尾数。这样做是因为数的平方根的指数大约为一半。
假设我们想要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] 删除。
我来说两句