我有一个问题不是关于算法,而是快速反平方根中的语法:
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the...?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
我不懂行
i = * (long * ) &y;
y = * (float * ) &i;
我知道“& y”是y的内存地址,但我不知道“(long *)”是什么意思,或者开头的星号在做什么。
答案 0 :(得分:1)
让我们声明一个整数: int main(){
char buffer[100];
int x;
char y;
read_line("x: ", buffer,sizeof(buffer));
sscanf(buffer, "%d", &x);
while(1){
read_line("y: ", buffer,sizeof(buffer));
printf("%d\n", x);
sscanf(buffer, "%s", &y);
printf("%d\n", x);
}
return 0;
}
现在让我们使用""地址获取foo的地址。运营商int foo;
。 &
返回指向-in的情况 - 整数:
&
上面的示例是存储解除引用int *bar = &foo;
,并将返回值转换为y
或指向* long
的指针。
答案 1 :(得分:1)
(long * )
是一个演员,它基本上告诉编译器嘿,对待这个
浮点指针,好像它是一个长指针。
开头的*
是用于取消引用的一元运算符
指针。取消引用意味着通过指针访问内存:
int a = 10;
int *p = &a;
printf("%d\n", *p);
会打印10.它与执行p[0]
相同。
所以
i = * (long * ) &y;
基本上是这样做的:将y
视为指向long
的指针并保存。{
y
中i
指向的值。
这样做是将float
值的内部位模式复制到i
。
现在i
将有一个基于该位模式的值。
y = * (float * ) &i;
这是相同的事情,但这次的价值为i
。
使用此代码确实通过float
修改long
位模式。该
代码甚至包含在评论 // evil floating point bit level hacking
中。
我不能告诉你它是如何工作的,因为我不知道快速反平方根算法。
答案 2 :(得分:1)
这是一个有趣的黑客,它基于32位整数和单精度浮点数的x86表示。如果没有测试,我认为它确实可以作为函数的一些近似值。
浮点数的*(long*)
转换实际上采用浮点数(指数和小数位)表示的位,并按相同的顺序将它们分配给32位整数。基于地址的转换可确保在路上不会发生重新格式化,例如舍入,而int值将逐位等同于原始浮点值。即。
s exponent fraction
(float) y = 0 10000000 10010010000111111011011
i = *(long*) y;
==> long int value
(long) i = 0 10000000 10010010000111111011011
然后对int值进行操作,包括右移'1',它影响int中的所有位,将所有指数和分数位向右移动并从常量中减去它。我不理解这部分背后的逻辑,但它导致了一个新的指数和分数位集,仍然以整数形式保存。
下一次转换为*(float*)
将再次使浮点数与整数相同,但允许计算机将其用作浮点数并对其进行浮点运算。
因此,它仅适用于一组硬件平台,仅适用于32位算术。