繁体   English   中英

快速平方根逆算法中第一种类型校正的确切值是多少?

[英]What is the exact value of the first type-punning in fast square root inverse algorithm?

有了这段代码,(这是Quake 3中使用的众所周知的快速平方根逆算法),我无法理解打印输出。 我从表面上了解了整个算法,但希望获得深入的了解。 printf打印时i的值是什么? 这给了我1120403456。 是否取决于计算机的体系结构? 我读过某处这样的类型操纵会导致不确定的行为。 在另一个网站上,我读到了那时i的值是此变量使用的位的确切值。 我对此感到困惑,并且诚实地期望i的值为100。如何解释结果1120403456? 如何将此值转换为十进制100? 这些位是以某种方式编码的吗? 这是代码摘录:

#include<stdio.h>

int main()
{
float x = 100;
float xhalf = 0.5f*x;
int i = *(int*)&x;
printf("%d", i);
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f-xhalf*x*x);
return x;

}

int i = *(int*)&x;之后打印的i的值int i = *(int*)&x; 是浮点数100.0的位表示形式,这是x初始化的对象。 由于您在printf使用%d格式,因此它将表示形式打印为十进制整数。

的位模式100.0在IEEE 32位float0x42c80000 ,这是1120403456十进制

要将1120403456或任何其他数字解释为IEEE基本的32位二进制浮点数:

  • 将数字写为32位,在这种情况下为01000010110010000000000000000000。
  • 第一位是符号。 0是+,而1是-。
  • 接下来的八位是指数的编码。 它们是10000101,即十进制133。 指数使用偏差127进行编码,这意味着所表示的2的实际幂是2 133-127 = 2 6 (如果指数为0或255,则这是一个具有不同含义的特殊值。)
  • 其余23位对有效位数进行编码。 对于普通指数(代码1到254),它们对以“ 1”开头并附加23位“ 10010000000000000000000”以形成二进制数“ 1.10010000000000000000000”而形成的有效位数进行编码。 以十进制表示,为1.5625。
  • 编码的完整值是带2的幂乘以有效数的符号:+ 2 6 •1.5625,等于64•1.5625,即100。

如果指数代码为0,则表示2 -126 ,并且有效位数将以“ 0.”而不是“ 1”开头。

如果指数代码为255,且有效位为零,则对象将表示无穷大(根据符号位为+∞或-∞)。 如果指数代码为255,并且有效位不为零,则该对象将表示非数字(NaN)。 NaN还有其他语义未包含在此答案中。

比Quake III早得多 ,尽管确切的魔术常数有所变化。

根据IEEE-754(大多数现代计算机使用的)对有限单精度浮点数进行编码是

     31 30           23 22                                          0
     ├─┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┤
     │S│   Exponent    │                   Mantissa                  │
     └─┴───────────────┴─────────────────────────────────────────────┘

最高位S是符号。 如果设置,则该值为负,否则为正。

如果ExponentMantissa均为零,则值为0.0(如果S为零)或-0.0(如果S为1)。

如果Exponent为零,但Mantissa非零,则您有一个非常接近零的非正规数

Exponent为255(所有位均已设置)的表示形式保留为无穷大(如果Mantissa为零),而不是数字(如果Mantissa不为零)。

对于从1到254(含)之间的Exponent值, Mantissa包含Mantissa小数位,在整数位置含一个隐式1(这是(1)0 10000001 (1)1011011011011011011011 。)换句话说,对于这些Exponent值, Mantissa表示的值是从1.00000000000000000000000 2 (十进制1.0)到1.11111111111111111111111 2 (十进制1.99999994)(含)。

= Exponent (between 1 and 254, inclusive), and the logical value of Mantissa (between 1.0 and 1.99999994), then the value the single-precision floating point represents is 现在,如果我们仅考虑非负值( S清除), = Exponent (1到254之间,包括1和254之间),而Mantissa的逻辑值(1.0到1.99999994之间),则值为单精度浮点点代表是

= 2 - 127 × = 2 -127 ×

127是指数偏差。 is 平方根是

= 2 ( - 127)/2 × √ = 2 /2 - 127 × 2 63 × √2 × √ = - 127)/ = 2 / 2 - 127×2 63×√2×√

和平方根反比,这是这里的目标运算,

= 2 (127 - )/2 × 1/√ = 2 - /2 - 127 × 2 63 × √2 × 1/√ 1 = 2(127 - 2×1 = 2 - / 2 - 127×2 63×√2×1 /√

注意2127/2 = 2 63.5 = 2 63 ×√2。

. 如果我们采用整数表示形式,并将其向右移一位,我们实际上将减半。 要乘以2 63 ,我们需要将63加到指数上。 63×2 23 , we effectively just multiply by /2. 然而代替,对于平方根运算,乘以√2×√ ,我们有效地只是乘以 / 2。 这意味着(将整数表示右移一位,然后将63加到指数上)会得出平方根的估计值,对于大于1.0的自变量,其平方差在0.7071067到0.75之间,而系数在0.7071067到0.05之间。 0和1之间的值是1448.155(对于√0,它的输出为5.421×10 -20,对于√1,它的输出为0.75。)

. 注意,对于平方根的倒数运算,我们希望对求反。

). 事实证明,如果向右一位移位整数表示,然后减去从(1 01111100 1101110101100111011111)2(1597463007十进制,十六进制0x5f3759df,的√2127≈1304381​​7825332782212单精度浮点近似值) ,你得到的平方根的倒数(1 的一个很好的近似。 对于所有有限的普通自变量,近似值与正确值之间的距离为0.965624至1.0339603。 一个非常好的近似值! 对于顶部的平方根逆运算,您需要做的是一两次牛顿方法迭代。 ) = 0 iff = 1/√ you need f( ) = 1/ ^2 - . So, each iteration in is - f( )/f'( ) = × (1.5 - 0.5 × × × . Which should look quite familiar.) (对于 0当且仅当 = 1 您需要 1 / ^ 2 - 因此,在每次迭代是 - ×(1.5-0.5× × × 。应该看起来很熟悉。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM