此代码来自UE4,我无法理解它。
static FORCEINLINE bool IsNaN( float A )
{
return ((*(uint32*)&A) & 0x7FFFFFFF) > 0x7F800000;
}
(uint32只是一个无符号的int)
第一部分是将一个浮点解释为一个uint32,这是一个简单的部分,但为什么是按位,它与0x7FFFFFFF
?最后4位告诉我们的是什么?为什么我们将结果与0x7F800000
进行比较?
答案 0 :(得分:4)
此定义遵循IEEE 754标准中提供的NaN定义。
在IEEE 754符合标准的浮点存储格式中,NaN由NaN独有的特定预定义位模式识别。
0x7FFFFFFF
是最大的值,可以用31位表示。在这种情况下,它只是忽略位符号,因为:
符号位无关紧要。
0x7F800000
是指数字段位的掩码。
例如,逐位IEEE浮点标准单精度 (32位)NaN将是:s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx其中s 是符号(在应用程序中经常被忽略),x是非零的 (零值编码无穷大)。
s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
s = 0
0x7FFFFFFF
(被x = 0
}和0x7F800000
忽略)等于operator >
。
x
,因为如果设置了有效数据中的任何位(任何0x7F800000
),则结果值将大于{{1}}。
为什么要设定?这是因为:
标准未定义剩余位[...]的状态/值,除非它们不能全为零。
来源:NaN on Wikipedia。
答案 1 :(得分:3)
这是NaN的定义。您可以在wikipedia上详细阅读
使用0x7FFFFFFF
是因为符号位在检查中无关紧要
定义说,对于nan,指数字段用1填充,而有些非零数字在有效数字中
0x7F80000
这是指数字段的位掩码。因此,如果在有效数字中设置了一个位,则该数字必须大于0x7F800000
请注意,假设sizeof(float) == 4
。
答案 2 :(得分:0)
您可以使用环境定义但具有历史问题的isnan实现(它是一个宏,然后成为tr1
下的函数,在某些实现中仍然是宏)。
或者,如果您无法在标准库中跟踪它,您可以依赖IEEE标准,声明NaN值具有与其自身不同的特殊属性:f != f
。
查看来自 IEEE-754 委员会的Stephen Canon的really interesting answer,并解释其背后的基本原理。
请注意,当打开某些优化标记时(例如-ffast-math
上的gcc
),并非所有编译器都会尊重这一点。