具有相同参数的函数不会 return 相同的值
Function with the same argument does not return the same value
我通过尝试优化某些东西(更少的变量等)来“玩”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()
可能会令人惊讶。
代码编译后我遇到的问题是,每次使用相同参数调用此函数都会给出相同的 return 值:有时这个值为负,有时为正(但绝对值始终相同)。
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 ) );
}
对于这段代码,我想说没有类型大小的问题,因为源代码(在上面的 link 中可见)已经使用了 double type
,它表示为 64我架构上的位(而不是 32 位上的 float
)。
我真的不明白为什么我用第一个函数就可以得到否定的答案...
感谢您的帮助。
正如 Barmar 所说,将 i 初始化为 0 是可行的。我还认为最好避免取消对具有其他大小的类型的引用(例如 *(uint64_t *) &x
,其中 x 是浮点数)。使用 uint32_t
取消引用可能更好,然后将结果正确地转换为 64 位变量。
我通过尝试优化某些东西(更少的变量等)来“玩”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()
可能会令人惊讶。
代码编译后我遇到的问题是,每次使用相同参数调用此函数都会给出相同的 return 值:有时这个值为负,有时为正(但绝对值始终相同)。
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 ) );
}
对于这段代码,我想说没有类型大小的问题,因为源代码(在上面的 link 中可见)已经使用了 double type
,它表示为 64我架构上的位(而不是 32 位上的 float
)。
我真的不明白为什么我用第一个函数就可以得到否定的答案...
感谢您的帮助。
正如 Barmar 所说,将 i 初始化为 0 是可行的。我还认为最好避免取消对具有其他大小的类型的引用(例如 *(uint64_t *) &x
,其中 x 是浮点数)。使用 uint32_t
取消引用可能更好,然后将结果正确地转换为 64 位变量。