简体   繁体   English

了解快速反平方根中的指针语法

[英]Understanding pointer syntax in fast inverse square root

I have a question that's not so much about the algorithm, but the syntax in the fast-inverse square root: 我有一个问题,与算法无关,而是快速反平方根中的语法:

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 don't understand the lines 我不懂台词

i = * (long * ) &y;
y = * (float * ) &i;

I know that "&y" is the memory address of y, but I don't know what "(long * )" means, or what the asterisk at the start is doing. 我知道“&y”是y的内存地址,但是我不知道“(long *)”是什么意思,也不知道星号开头的含义。

Let's declare an integer: int foo; 让我们声明一个整数: int foo;

Let's now get the address of foo with the "address of" operator & . 现在,使用运算符&的“地址”获取foo的地址。 The & returns a pointer to -in this case- an integer: &返回指向-在这种情况下-整数的指针:

int *bar = &foo;

The example above is storing dereferencing y , and casting the return value to * long , or a pointer to a long int . 上面的示例存储了对y解引用,并将返回值强制转换为* long ,或将指针转换为long int

The (long * ) is a cast, it's basically telling the compiler hey, treat this float pointer as if it were a long pointer . (long * )是强制类型转换,基本上是告诉编译器嘿,将此float指针视为long指针

The * at the beginning is the unary operator that is used to dereference pointers. 开头的*是一元运算符,用于取消引用指针。 Dereference means access the memory through a pointer: 解除引用意味着通过指针访问内存:

int a = 10;
int *p = &a;

printf("%d\n", *p);

Would print 10. It's the same as doing p[0] . 将打印10。与执行p[0]

So 所以

i = * (long * ) &y;

is basically doing: treat y as if it were a pointer to long and save the value pointed to by y in i . 基本上是在做:将y视为指向long的指针,然后将y指向的值保存在i

What this does is copying the internal bit pattern of the float value to i . 这是将float值的内部位模式复制到i Now i will have a value based on that bit pattern. 现在, i将基于该位模式获得一个值。

y = * (float * ) &i;

This does the same thing but with this time with the value of i . 这做同样的事情,但是这次是i的值。

With this code does is modifying the float bit pattern through a long . 使用此代码可以通过long修改float位模式。 The code even has in the comment // evil floating point bit level hacking . 该代码甚至在注释中有// evil floating point bit level hacking I cannot tell you how this works, because I don't know the fast inverse square root algorithm. 我无法告诉您这是如何工作的,因为我不知道快速反平方根算法。

this is an interesting hack based on the x86 representation of 32 bit integer and single precision floating point numbers. 这是一个有趣的技巧,它基于32位整数和单精度浮点数的x86表示形式。 Without testing I assume that it really works as some approximation of the function. 未经测试,我认为它确实可以作为该函数的近似函数。

The *(long*) conversion of the float number actually takes the bits as represented int the float (exponent and fraction bits) and assigns them to a 32-bit integer in the same order. 浮点数的*(long*)转换实际上采用浮点数表示的位(指数和小数位),并将它们按相同顺序分配给32位整数。 The address based casting guarantees that that no reformatting would happen on the way, like rounding and the int value will be bit by bit equivalent to the original float value. 基于地址的强制转换保证不会重新格式化,例如舍入,并且int值将一点一点地等同于原始float值。 ie

             s exponent fraction
 (float) y = 0 10000000 10010010000111111011011

 i = *(long*) y;

  ==>        long int value 
 (long)  i = 0 10000000 10010010000111111011011

then there is an operation on the int value, including shift right by '1' which affects all bits in the int, moving all exponent and fraction bits right and subtracting it from a constant. 然后对int值进行一个运算,包括向右移位“ 1”,这会影响int中的所有位,将所有指数和小数位右移并从常数中减去。 I do not understand the logic behind this part, but it results in a new set for the exponent and fraction bits, still preserved in an integer form. 我不了解这部分背后的逻辑,但它会为指数位和小数位产生新的集合,但仍保留为整数形式。

And the next conversion to *(float*) will again make the float bit-by-bit identical to the integer, but will allow the computer to use it as float and do float arithmetic on it. 下一次到*(float*)转换将再次使浮点数与整数完全相同,但是将允许计算机将其用作浮点并对它进行浮点运算。

So, it will work for a set of hardware platforms only and for 32-bit arithmetic only. 因此,它将仅适用于一组硬件平台,并且仅适用于32位算术。

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

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