[英]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位float
是0x42c80000
,这是1120403456
十进制
要将1120403456或任何其他数字解释为IEEE基本的32位二进制浮点数:
如果指数代码为0,则表示2 -126 ,并且有效位数将以“ 0.”而不是“ 1”开头。
如果指数代码为255,且有效位为零,则对象将表示无穷大(根据符号位为+∞或-∞)。 如果指数代码为255,并且有效位不为零,则该对象将表示非数字(NaN)。 NaN还有其他语义未包含在此答案中。
它比Quake III早得多 ,尽管确切的魔术常数有所变化。
根据IEEE-754(大多数现代计算机使用的)对有限单精度浮点数进行编码是
31 30 23 22 0
├─┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┤
│S│ Exponent │ Mantissa │
└─┴───────────────┴─────────────────────────────────────────────┘
最高位S
是符号。 如果设置,则该值为负,否则为正。
如果Exponent
和Mantissa
均为零,则值为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≈13043817825332782212单精度浮点近似值) ,你得到的平方根的倒数(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.