Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What is std::nan can be used for?

74 views
Skip to first unread message

mirm...@gmail.com

unread,
Nov 28, 2017, 3:36:44 AM11/28/17
to
Hello comrades.

I expected that std::nan is a constant (double) Nan, but it turns out that it is a function that takes a string argument and sets Nan with a mantissa corresponding to processing this string argument with a function strtod...

I only have one question ... Why would this be necessary ???

James R. Kuyper

unread,
Nov 28, 2017, 11:22:22 AM11/28/17
to
<https://en.wikipedia.org/wiki/IEEE_754#Formats>: "A NaN may carry a
payload that is intended for diagnostic information indicating the
source of the NaN." A NaN is represented by a biased-exponent field that
is filled with 1 bits, and a non-zero significand. The payload is stored
in the significand.
I'd cite IEEE 754 directly, if I could - but I don't have a copy of it.
I do have a copy of IEEE 854, which is a radix-independent variant of
IEEE 754, but I don't have it with me right now.

C++ does not mandate conformance with IEEE 754, but if
std::numeric_limits<T>::is_iec559 is true, then T conforms to IEC 559
(== ANSI/IEEE 754), and that is is overwhelmingly the most commonly
supported floating point standard. I think that some of the other
floating point standards may have a similar feature.

The specification for the strtod() function is incorporated by reference
from the C standard. Section 7.22.1.3p3 and p4 of the C standard specify
that a string starting with an optional sign followed by NAN will
produce a NAN, and that the "NAN" may optionally followed by sequence of
digits and nondigits - which sequences are allowed and what they mean is
implementation-defined (you might expect that everything is either a
digit or a non-digit, but that's not how those terms are defined. The
character '_', the roman letters 'a' through 'z' and 'A' through 'Z',
and any UCN are guaranteed to qualify as nondigits. Any other characters
that qualify as nondigits are implementation-defined - C standard
6.4.2.1p1).

The description of the iostreams library does not describe the handling
of NANs directly - it describes the relevant functions as equivalent to
calls to members of the printf() family of functions. The definitions of
those functions are incorporated by reference from the C standard.
Section 7.21.6.1p8 of the C standard specifies that if you print a NaN,
the output will start with an optional '-' followed by "nan" (if you use
%f, %e, %g, or %a) or "NAN" (if you use %F, %E, %G, or %A) optionally
followed by an implementation-defined sequence of characters.

Both ends of this process are entirely implementation-defined, which
allows an implementation to make full use of IEEE 754 NaNs with
payloads, or not, at the implementor's discretion. I would expect most
implementations which support NaN payloads to define the character
string produced by printf() of a NaN to match the string passed to
strtod() to create that NaN.

Thus, code which creates a NaN using strtod() can encode a limited
amount of information about the context in which it was created, which
can be decoded by printing the NaN.

Alf P. Steinbach

unread,
Nov 28, 2017, 11:42:13 AM11/28/17
to
With IEEE 754, which is the most common floating point format, there is
not one single NaN value, but a multitude. ¹`std::nan()` gives you an
implementation-defined way to generate specific values of that
multitude, when the floating point format supports NaN.
²`std::numeric_limits<T>::quiet_NaN`, with `T` a floating point type,
gives you a particular one of those values; in practice it's the one
that gives the cleanest text representation, just “NaN”.

To check for NaN-value, with modern compilers as of 2017 use ³`std::isnan`.

With older compilers it was difficult to check for NaN-value. One could
not and can still not rely on NaN != NaN, because when you ask the
compiler (e.g. g++, Visual C++) to optimize floating point operations
it's likely to optimize away that special behavior of NaN. Just keep in
mind that NaN is VERY tricky and slippery and a joker, like Loki.

Cheers & hth.,

- Alf

Links:
¹ http://en.cppreference.com/w/cpp/numeric/math/nan
² http://en.cppreference.com/w/cpp/types/numeric_limits/quiet_NaN
³ http://en.cppreference.com/w/cpp/numeric/math/isnan

Chris Ahlstrom

unread,
Nov 28, 2017, 4:53:24 PM11/28/17
to
Alf P. Steinbach wrote this copyrighted missive and expects royalties:

> On 11/28/2017 9:36 AM, mirm...@gmail.com wrote:
>>
>> I expected that std::nan is a constant (double) Nan, but it turns out
>> that it is a function that takes a string argument and sets Nan with
>> a mantissa corresponding to processing this string argument with a
>> function strtod...
>>
>> I only have one question ... Why would this be necessary ???
>
> With IEEE 754, which is the most common floating point format, there is
> not one single NaN value, but a multitude. ¹`std::nan()` gives you an
> implementation-defined way to generate specific values of that
> multitude, when the floating point format supports NaN.
> ²`std::numeric_limits<T>::quiet_NaN`, with `T` a floating point type,
> gives you a particular one of those values; in practice it's the one
> that gives the cleanest text representation, just “NaN”.
>
> To check for NaN-value, with modern compilers as of 2017 use ³`std::isnan`.
>
> With older compilers it was difficult to check for NaN-value. One could
> not and can still not rely on NaN != NaN, because when you ask the
> compiler (e.g. g++, Visual C++) to optimize floating point operations
> it's likely to optimize away that special behavior of NaN. Just keep in
> mind that NaN is VERY tricky and slippery and a joker, like Loki.

Loki, Not a Norse god?
- - -

--
After all, all he did was string together a lot of old, well-known quotations.
-- H. L. Mencken, on Shakespeare

Alf P. Steinbach

unread,
Nov 28, 2017, 5:57:21 PM11/28/17
to
On 11/28/2017 10:39 PM, Chris Ahlstrom wrote:
>> compiler (e.g. g++, Visual C++) to optimize floating point operations
>> it's likely to optimize away that special behavior of NaN. Just keep in
>> mind that NaN is VERY tricky and slippery and a joker, like Loki.
> Loki, Not a Norse god?

https://en.wikipedia.org/wiki/Loki

That is, the Norse being, not the library.

Cheers!,

- Alf

James R. Kuyper

unread,
Nov 29, 2017, 8:57:57 AM11/29/17
to
On 11/29/2017 03:58 AM, Stefan Ram wrote:
> ECMA-262 says it in all its glory:
>
> |The Number type has exactly 18437736874454810627 (that is,
> |2^64-2^53+3) values, representing the double-precision 64-bit
> |format IEEE 754-2008 values as specified in the IEEE Standard
> |for Binary Floating-Point Arithmetic, except that the
> |9007199254740990 (that is, 2^53-2) distinct “Not-a-Number”
> |values of the IEEE Standard ...
>
> BTW, did you guys know that ECMA-262 is a normative
> reference of ISO 14882?

What ECMA-262 has to say about it's Number type is relevant to C++ only
in the context of <regex>, the only place where ECMA-262 is mentioned
(and ECMA-262's Number type isn't mentioned directly anywhere).

IEC 559 (== ANSI/IEEE 754) is the relevant standard, and even then, only
if std::numeric_limits<T>::is_iec559 is true.

Christian Gollwitzer

unread,
Nov 29, 2017, 4:03:51 PM11/29/17
to
Am 28.11.17 um 17:42 schrieb Alf P. Steinbach:
> To check for NaN-value, with modern compilers as of 2017 use
> ³`std::isnan`.
>
> With older compilers it was difficult to check for NaN-value. One could
> not and can still not rely on NaN != NaN, because when you ask the
> compiler (e.g. g++, Visual C++) to optimize floating point operations
> it's likely to optimize away that special behavior of NaN.

How "old" a compiler are you talking about? I've used a!=a for ages to
watch for NaN, and ordering the comparisons in a way that it does the
right thing with a NaN (i.e. a > 5 vs. ! (a <= 5) ).

Maybe if you use -ffast-math these things get optimized away, but I'm
not convinced that this buys you so much that it is worth. Without
-ffast-math you still have optimizations.

I've also seen that mostly NaN became a slow path of execution. When all
of the data became NaN, the whole computation slowed down by a factor of
2-3.

Christian
0 new messages