...one of the most highly
regarded and expertly designed C++ library projects in the
world.

— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards

The C++98 standard does not specify how *infinity* and
*NaN* are represented in text streams. As a result, different
platforms use different string representations. This can cause undefined
behavior when text files are moved between different platforms. Some platforms
cannot even input parse their own output! So 'route-tripping' or loopback
of output to input is not possible. For instance, the following test fails
with MSVC:

stringstream ss; double inf = numeric_limits<double>::infinity(); double r; ss << inf; // Write out. ss >> r; // Read back in. cout << "infinity output was " << inf << endl; // 1.#INF cout << "infinity input was " << r << endl; // 1 assert(inf == y); // Fails!

The facets `nonfinite_num_put`

and `nonfinite_num_get`

format
and parse all floating-point numbers, including `infinity`

and `NaN`

, in a consistent
and portable manner.

The following test succeeds with MSVC.

locale old_locale; locale tmp_locale(old_locale, new nonfinite_num_put<char>); locale new_locale(tmp_locale, new nonfinite_num_get<char>);

Tip | |
---|---|

To add two facets, Or you can create a new locale in one step
and, for example, use it to imbue an input and output stringstream. |

Tip | |
---|---|

To just change an input or output stream, you can concisely write |

stringstream ss; ss.imbue(new_locale); double inf = numeric_limits<double>::infinity(); ss << inf; // Write out. assert(ss.str() == "inf"); double r; ss >> r; // Read back in. assert(inf == r); // Confirms that the double values really are identical. cout << "infinity output was " << ss.str() << endl; cout << "infinity input was " << r << endl; // But the string representation of r displayed will be the native type // because, when it was constructed, cout had NOT been imbued // with the new locale containing the nonfinite_numput facet. // So the cout output will be "1.#INF on MS platforms // and may be "inf" or other string representation on other platforms.

C++0X (final) draft standard does not explicitly specify the representation (and input) of nonfinite values, leaving it implementation-defined. So without some specific action, input and output of nonfinite values is not portable.

The C99
standard **does** specify how infinity
and NaN are formatted by printf and similar output functions, and parsed
by scanf and similar input functions.

The following string representations are used:

**Table 2.1. C99 Representation of Infinity and NaN**

number |
string |
---|---|

Positive infinity |
"inf" or "infinity" |

Positive NaN |
"nan" or "nan(...)" |

Negative infinity |
"-inf" or "-infinity" |

Negative NaN |
"-nan" or "-nan(...)" |

So following C99 provides a sensible 'standard' way of handling input and output of nonfinites in C++, and this implementation follows most of these formats.

A particular type of NaN is the signaling NaN. The usual mechanism of signaling is by raising a floating-point exception. Signaling NaNs are defined by IEEE 754-2008.

Floating-point values with layout *s*111 1111 1*a*xx
xxxx xxxx xxxx xxxx xxxx where *s* is the sign, *x*
is the payload, and bit *a* determines the type of NaN.

If bit *a* = 1, it is a quiet NaN.

If bit *a* is zero and the payload *x*
is nonzero, then it is a signaling NaN.

Although there has been theoretical interest in the ability of a signaling
NaN to raise an exception, for example to prevent use of an uninitialised
variable, in practice there appears to be no useful application of signaling
NaNs for most current processors. C++0X
18.3.2.2 still specifies a (implementation-defined) representation
for signaling NaN, and `static constexpr bool has_signaling_NaN`

a method of checking
if a floating-point type has a representation for signaling NaN.

But in practice, most platforms treat signaling NaNs in the same as quiet
NaNs. So, for example, they are represented by "nan" on output
in C99
format, and output as `1.#QNAN`

by Microsoft compilers.

Note | |
---|---|

The C99 standard does not distinguish between the quiet NaN and signaling NaN values. A quiet NaN propagates through almost every arithmetic operation without raising a floating-point exception; a signaling NaN generally raises a floating-point exception when occurring as an arithmetic operand. C99 specification does not define the behavior of signaling NaNs. NaNs created by IEC 60559 operations are always quiet. Therefore this implementation follows C99, and treats the signaling NaN bit as just a part of the NaN payload field. So this implementation does not distinguish between the two classes of NaN. |

Note | |
---|---|

An implementation may give zero and non-numeric values (such as infinities and NaNs) a sign or may leave them unsigned. Wherever such values are unsigned, any requirement in the C99 Standard to retrieve the sign shall produce an unspecified sign, and any requirement to set the sign shall be ignored.
This might apply to user-defined types, but in practice built-in floating-point
types |

The numbers can be of type `float`

,
`double`

and ```
long
double
```

. An optional + sign can be
used with positive numbers (controlled by ios manipulator `showpos`

).
The function `printf`

and similar
C++ functions use standard formatting flags to put all lower or all upper
case (controlled by `std::ios`

manipulator `uppercase`

and `lowercase`

).

The function `scanf`

and similar
input functions are case-insensitive.

The dots in `nan(...)`

stand for an arbitrary string. The meaning of that string is implementation
dependent. It can be used to convey extra information about the NaN, from
the 'payload'. A particular value of the payload might be used to indicate
a *missing value*, for example.

This library uses the string representations specified by the C99 standard.

An example of an implementation that optionally includes the NaN payload information is at AIX NaN fprintf. That implementation specifies for Binary Floating Point NANs:

- A NaN ordinal sequence is a left-parenthesis character '(', followed by a digit sequence representing an integer n, where 1 <= n <= INT_MAX-1, followed by a right-parenthesis character ')'.
- The integer value, n, is determined by the fraction bits of the NaN argument value as follows:
- For a signalling NaN value, NaN fraction bits are reversed (left to right) to produce bits (right to left) of an even integer value, 2*n. Then formatted output functions produce a (signalling) NaN ordinal sequence corresponding to the integer value n.
- For a quiet NaN value, NaN fraction bits are reversed (left to right) to produce bits (right to left) of an odd integer value, 2*n-1. Then formatted output functions produce a (quiet) NaN ordinal sequence corresponding to the integer value n.

Warning | |
---|---|

This implementation does not (yet) provide output of, or access to, the NaN payload. |