Re: [googletest] EXPECT_FLOAT_EQ and NaN's

6,044 views
Skip to first unread message

Keith Ray

unread,
Sep 24, 2012, 9:30:32 AM9/24/12
to Jens Thielemann, googletes...@googlegroups.com
For all kinds of Not a Number (NAN)...
NAN != NAN is true (I think)
NAN == NAN is false
NAN != any number is true (I think)
NAN == any number is false
NAN < any number is false (I think)
NAN > any number is false (I think)

so the basic macros, which use equality and other comparison operators, are not going to work with NAN values.

Is there a function like is_nan() you can use?

otherwise you can write a macro that relies on < and > and == all being false for NAN values.

--
C. Keith Ray
twitter: @ckeithray
phone: 650-KEY-4RAY
       650-539-4729




On 2012 Sep 24, at 1:14 AM, Jens Thielemann wrote:

Hi!

I am unable to get EXPECT_FLOAT_EQ to work with NaN's. 

In some cases, the expected answer of a calculation is NaN (i.e. to signal that the calculation was not possible to perform). However, if I write

float nan = std::numeric_limits<float>::quiet_NaN();
 
EXPECT_FLOAT_EQ(nan, myresult);

and myresult is (correctly) nan, then the assertion fails. 

Is this a bug? How can I accomplish the intended behaviour (checking all non-NaN's with some tolerance but also checking that reference NaN's are found)?

I am using version 1.6.0. 

Regards,

Jens Thielemann

Ken Turkowski

unread,
Oct 2, 2012, 12:36:26 AM10/2/12
to Keith Ray, Jens Thielemann, googletes...@googlegroups.com
It all depends on what compiler/machine/OS you are on. The spec says that Nan is not comparable to anything, even itself. This means that all comparisons involving a NaN should fail.

However, one test that works on most systems is

    if (!(a == a))
         FoundANaN(a);

but, I believe that this does not work on MSVC, probably because it uses a shortcut that is invalid for NaNs. However, you can probably use

    if (!(a <= a))
        FoundANaN(a);

or

   EXPECT_TRUE(!(a <= a));

Note that, there are many different kinds of NaNs (16 million for float32, 8 quadrillion for float64). Half of them are signaling, and half of them are non-signalling. Then, they can carry a payload and a sign. So you can't even compare a canonical Nan as bits to an arbitrary Nan and expect them to be equal.

math.h has isnan() on many systems. Or you can roll your own: if the exponent is the maximum value and the significand is nonzero, it is a Nan.

Ken Turkowski

unread,
Oct 2, 2012, 3:25:58 PM10/2/12
to Ken Turkowski, Keith Ray, Jens Thielemann, googletes...@googlegroups.com
Note that
if (!(a == a))
is not the same as
if (a != a)
when one of the arguments is a NaN.
Similarly
if (!(a <= a))
is not the same as
if (a > a)
when one of the operands is a Nan.

Matthew Woehlke

unread,
Oct 4, 2012, 4:59:59 PM10/4/12
to Google C++ Testing Framework, Ken Turkowski, jen...@gmail.com
(resend to list... sorry, Ken)

On 2012-10-02 15:25, Ken Turkowski wrote:
> Similarly
> if (!(a <= a))
> is not the same as
> if (a > a)
> when one of the operands is a Nan.

Correct; I would expect the results of the above to be true and false,
respectively, because any ordering comparison with NaN gives false (even
the same NaN compared against itself). However...

> Note that
> if (!(a == a))
> is not the same as
> if (a != a)
> when one of the arguments is a NaN.

...really? According to Wikipedia[1], "every NaN compares unequal to
every value, including itself", therefore I would expect both of the
above to be true for 'a' being a NaN.

I can confirm this on x86_64 with 'a' being a double, and have no reason
to expect the result would be different on any platform form any IEEE
754 conforming data type.

Also, while 'a > b' != '!(a <= b)' is reasonably understood in the
presence of values that cannot be ordered with respect to each other, I
would find any instance of '!(a == b)' != 'a != b' to be surprising,
regardless of whether or not b is an alias for a.

1:
http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

--
Matthew

Jens Thielemann

unread,
Oct 5, 2012, 4:59:39 PM10/5/12
to Matthew Woehlke, Google C++ Testing Framework, Ken Turkowski
Hi!

Thanks for replying. 

However, what I was looking for was to use the Google Test framework to actually verify that the output of a function indeed was NaN (in this case, the one returned by std::numeric_limits<float>::quiet_NaN()), without having to roll something on top on EXPECT_PRED_FORMAT2 myself. I was hoping this was already in the framework, but from your that does not seem to be the case.  

Jens

Matthew Woehlke

unread,
Oct 5, 2012, 6:41:00 PM10/5/12
to Jens Thielemann, Google C++ Testing Framework, Ken Turkowski
EXPECT_PRED_FORMAT is overkill... as stated earlier in the thread, I
would recommend EXPECT_TRUE(isnan(a)).

(Unless you really need *bitwise* equality, in which case I wouldn't
expect there to be something existing anyway. Testing that you get a
*specific* NaN is a bit esoteric, IMO.)

Matthew

On 2012-10-05 16:59, Jens Thielemann wrote:
> Hi!
>
> Thanks for replying.
>
> However, what I was looking for was to use the Google Test framework to
> actually verify that the output of a function indeed was NaN (in this case,
> the one returned by std::numeric_limits<float>::quiet_NaN()), without
> having to roll something on top on *EXPECT_PRED_FORMAT2 **myself. I was
> hoping this was already in the framework, but from your that does not seem
> to be the case. ** *
> *
> *
> *Jens*
>> 1: http://en.wikipedia.org/wiki/**Floating_point#IEEE_754:_**
>> floating_point_in_modern_**computers<http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers>
>>
>> --
>> Matthew
>>
>

Gavin Kingsley

unread,
Jul 17, 2017, 3:44:36 AM7/17/17
to Google C++ Testing Framework, jen...@gmail.com, realit...@gmail.com
Here is an updated answer using gmock matchers:

#include "gtest/gtest.h"
#include "gmock/gmock.h"
...
  EXPECT_THAT(myresult, ::testing::NanSensitiveFloatEq(nan));

myresult will now print to the output stream when the test fails.


--Gavin.
Reply all
Reply to author
Forward
0 new messages