问题描述
我通过尝试优化某些东西(更少的变量等)来“玩”fast inverse sqrt 函数。最终代码如下:
float Q_rsqrt(float x) {
const float x2 = x * 0.5F;
uint_fast32_t i;
memcpy(&i,&x,sizeof(float));
i = 0x5f3759df - ( i >> 1 );
memcpy(&x,&i,sizeof(float));
return x * ( 1.5F - ( x2 * x * x ) );
}
首先,了解在我的架构中 uint_fast32_t
以 64 位表示而 float
以 32 位表示是很有用的。因此,在不同大小的变量类型上生成 memcpy()
可能会令人惊讶。
我在编译代码后遇到的问题,每次使用相同参数调用此函数都会给出相同的返回值:有时这是负数,有时是正值(但始终具有相同的绝对值)。
memcpy()
的用处是绕过以下代码的警告(取消引用类型双关指针将破坏严格别名规则)(完全按预期工作):
float Q_rsqrt_test(float x) {
const float xHalf = x * 0.5F;
const uint_fast32_t i = 0x5f3759df - ( (* ( uint_fast32_t * ) &x) >> 1 );
x = * ( float * ) &i;
return x * ( 1.5F - ( xHalf * x * x ) );
}
对于这段代码,我想说没有类型大小的问题,因为源代码(在上面的链接上可见)已经使用了 double type
,它在我的架构上以 64 位表示(而不是float
的 32 位)。
感谢您的帮助。
解决方法
正如 Barmar 所说,将 i 初始化为 0 有效。我还认为最好避免取消引用具有其他大小的类型(例如 *(uint64_t *) &x
,其中 x 是浮点数)。使用 uint32_t
取消引用可能会更好,然后将结果正确转换为 64 位变量。