Checking if the float is not a number
This code is from UE4 and I am having some trouble understanding it.
static FORCEINLINE bool IsNaN( float A )
{
return ((*(uint32*)&A) & 0x7FFFFFFF) > 0x7F800000;
}
(uint32 is just unsigned int)
The first part is interpreting float as uint32, i.e. the easy part, but why bitwise and with 0x7FFFFFFF
? What are the last 4 bits telling us and why are we comparing the result with 0x7F800000
?
source to share
This definition follows the IEEE 754 definition of NaN.
In standard IEEE 754 compliant floating point storage formats, NaNs are identified by specific predefined bit patterns that are unique to NaN.
0x7FFFFFFF
- the largest value that can be represented by 31 bits. In this case, it just ignores the bit sign because:
The sign bit is irrelevant.
0x7F800000
is the mask for the bits of the exponential field.
For example, IEEE floating point standard single precision (32-bit) NaN would be: s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx, where s is a sign (most often ignored in applications) and x is nonzero (the value of zero encodes infinity) ...
Where s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
s s = 0
(ignored by 0x7FFFFFFF
) and x = 0
equal 0x7F800000
.
operator >
because if any bit in the value is set (any x
), the resulting value will be greater than 0x7F800000
.
And why should it be installed? Because:
The state / meaning of the remaining bits [...] is not defined by the standard, except that they must not be zero.
Source: NaN on Wikipedia .
source to share
This is the definition of NaN. You can read this in detail on wikipedia . 0x7FFFFFFF
used because the sign bit doesn't matter in the check.
The definition says that for nan, the exponential field is filled with ones, and some nonzero number is in the value.
0x7F80000
this is the bit mask for the exponential field. Therefore, if a bit is set to a value, the number must be greater than0x7F800000
Note that it is assumed that a sizeof(float) == 4
.
source to share
IsNaN ()
You can either use the isnan implementation, which is environment-defined but has historical problems (it was a macro and later became a function under tr1
and in some implementations is still a macro).
f! = f
Or, if you can not track it in its standard library, you can rely on the IEEE standard, indicating that NaN values are of particular property to be different from himself: f != f
.
Check out this really interesting answer from Stephen Canon who was on the IEEE-754 committee and explains the rationale behind it.
note that not all compilers will respect this when optimization flags are enabled (e.g. -ffast-math
on gcc
).
source to share