[C/C++] Floating point comparisons with NaN giving inconsistent results

You might notice that when comparing with NaN, the comparison gives wrong results at least for x64 builds. Take a look at the following piece of code. If you run this sample application the comparison statement if(lfv==0.0) returns true and the MessageBox is displayed. (We had a customer who reported this behavior.)

#include "stdafx.h"
#include <limits>


int _tmain(int argc, _TCHAR* argv[])
{
    double lfv = std::numeric_limits<double>::quiet_NaN();

    if (lfv == 0.0)
        ::MessageBox(::GetActiveWindow(), _T("Equal"), argv[0], MB_OK);

    return 0;
}

If you put a breakpoint at the if statement, this is what the debugger shows as values for lfv. lfv is definitely not zero.

image

So why is the comparison behaving weird. The reason for this issue is that you’ve disable precise comparison of floating point values via the compiler switch /fp:fast. To fix this you should change to /fp:precise. This can be done via project properties dialog as well…

image

So you might ask why does it behave well for x86 builds? The answer is that comparing NaN’s with /fp:fast result in undefined behavior. So it is OK for the comparisons to behave differently on different targets with this option.

You should be aware of all the implications of using /fp:fast in VC++ and one of them is undefined behavior for NaN comparisons. This is the way VC++ specifies how /fp:fast behaves and is likely due to implementation constraints. Other compilers may produce the correct result for such compares but that is because each compiler has its own specification of what /fp:fast means.

Now you might think just for one comparison should I enable /fp;precise? The answer is that you can enable this feature per compilation unit or per function. Check out following link for details: http://msdn.microsoft.com/en-us/library/45ec64h6.aspx

The above link talks about the float_control pragma. So in order to fix above code we can do this instead of turning on /fp:precise for the entire project…

#include "stdafx.h"
#include <limits>

#pragma float_control(precise, on)

int _tmain(int argc, _TCHAR* argv[])
{
    double lfv = std::numeric_limits<double>::quiet_NaN();

    if (lfv == 0.0)
        ::MessageBox(::GetActiveWindow(), _T("Equal"), argv[0], MB_OK);

    return 0;
}
#pragma float_control(precise, off)

Or if you have too many functions you can enable /fp:precise per cpp file or per compilation unit. Right click on the cpp file, select properties and navigate to the following property and change it to /fp:precise

image

This should will help solve your comparison failures with NaN values.

Appreciate your comments...