我正在研究一个平台,当将浮点数与零比较时,这个平台会出现可怕的停顿。作为优化,我看到使用了以下代码:
inline bool GreaterThanZero( float value )
{
const int value_as_int = *(int*)&value;
return ( value_as_int > 0 );
}
查看生成的程序集,档位消失了,功能更加高效。
这有用吗?我很困惑,因为IEEE技巧的所有优化都使用SIGNMASKS和许多AND / OR操作(例如http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf)。对有符号int的强制转换是否有帮助?在简单的线束中进行测试没有发现问题。
任何见解都会很好。
答案 0 :(得分:6)
表达式*(int*)&value > 0
测试value
是否为任何正浮点数,从最小的正规范(具有与0x00000001
相同的表示)到最大的有限浮点数(带有表示{{ 1}})和0x7f7fffff
(与+inf
具有相同的表示形式)。该技巧检测到多个(但不是全部)NaN表示为正(NaN表示高于0x7f800000
)。如果您不关心某些NaN值使测试成立,那就没问题了。
这一切都有效,因为IEEE {754格式的representation。
为了模拟IEEE 754操作,您在文献中看到的位操作函数可能旨在实现完美仿真,同时考虑0x7f800001
和带符号零的特定行为。例如,变体NaN
不等同于*(int*)&value >= 0
,因为value >= 0.0f
表示为-0.0f
作为无符号整数,因此0x80000000
表示为已签名一,使后一种情况成立,前者成为假。这可能会使这些功能变得非常复杂。
投射到签名的
-0x80000000
有帮助吗?
嗯,是的,因为int
和float
的符号位在同一个地方,并且两者都表示未设置时为正数。但条件int
可以通过将value > 0.0f
重新解释为无符号整数来实现。
注意:转换为value
地址的int*
会破坏严格的别名规则,但如果您的编译器保证它为这些程序赋予意义(可能使用命令行),这可能是可以接受的选项)。