2

If I print a NaN via std::cout or convert it to a string, does the standard say it has to be "nan" as a string?

Are there other methods to convert a NaN to a string, where this is not true?

#include <iostream>
#include <limits>

int main() {    

    float x = std::numeric_limits<float>::quiet_NaN();
    std::cout << x << '\n';                 // Output: nan
    std::cout << std::to_string(x) << '\n'; // Output: nan
    printf("%f", x);                        // Output: nan

    // possibly other variants to print x
}
nada
  • 2,109
  • 2
  • 16
  • 23
  • No. In Windows/VC++ it looks different. (Unfortunately, I forgot how.) However, I found this Q/A: [SO: NaN ASCII I/O with Visual C++](https://stackoverflow.com/q/7477978/7478597). (It shows what I roughly remembered.) – Scheff's Cat Jun 18 '19 at 10:03
  • Found the same link as @formerlyknownas_463035818. It might be a bug how things are done in VC++. Unfortunately, the resp. link of Hans Passant is rotten. – Scheff's Cat Jun 18 '19 at 10:12
  • I also ask about other variants than std::to_string, so not exactly a duplicate. – nada Jun 18 '19 at 10:15
  • i think [this answer](https://stackoverflow.com/a/7478290/4117728) covers using `cout` (even if the question is specifically about visual c++, I think the answer has a wider scope) – 463035818_is_not_an_ai Jun 18 '19 at 10:17
  • 2
    It drives me _crazy_ that Microsoft decided to summarily break all links to bug reports on their Connect platform, with absolutely no redirects or indeed any indication whatsoever how to find the moved content. It really says a lot about the culture there, in my opinion. – Lightness Races in Orbit Jun 18 '19 at 10:19
  • (Off-topic) Don't use `std::endl`, unless you really want a short form of `'\n' << std::flush`. – Nikos C. Jun 18 '19 at 10:23
  • @NikosC. Edited. Doesn't really matter here though. – nada Jun 18 '19 at 10:27
  • Infinity and negative infinity probably have similar portability concerns. – Eljay Jun 18 '19 at 10:47

2 Answers2

2

std::to_string is defined in terms of std::sprintf, which C++ adopts from the C99 standard library. And there it says:

Not-a-number is converted to nan or nan(char_sequence). Which one is used is implementation defined.

So the string will begin with nan, but there could be other characters after it.

Unfortunately, Microsoft's library doesn't seem to be compliant. See this answer:

https://stackoverflow.com/a/7478290/856199

So, after taking all that in, the end result is that your C standard library is not C99-compliant, since 1.#QNAN is not a valid output of fprintf according to the above. But, it's well-known that Microsoft's C runtime is not C99-compliant, and it doesn't plan to become compliant any time soon, as far as I'm aware.


(Off-topic)
Don't use std::endl, unless you really want a short form of '\n' << std::flush.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
1

Adding to @Nikos C. :

std::cout which is a std::basic_ostream leads to std::num_put about formatting which says

If the type of v is a floating-point type, the the first applicable choice of the following is selected:

If floatfield == std::ios_base::fixed, will use conversion specifier %f 
If floatfield == std::ios_base::scientific && !uppercase, will use conversion specifier %e 
If floatfield == std::ios_base::scientific, will use conversion specifier %E

So Im gonna conclude, that std::cout is also tied to printf

Narase
  • 490
  • 2
  • 12