Skip to main content
added 60 characters in body
Source Link
Marcus Müller
  • 36.9k
  • 4
  • 59
  • 105

Anyways, In C11 it is defined that the conversion is tofrom should be done "correctly rounded". And I'd tend to say that's what GCC does herehere; and the "should" gives leeway there, anyways. (And rounding a subnormal to 0 seems fine to me!)

Anyways, In C11 it is defined that the conversion is to be done "correctly rounded". And I'd tend to say that's what GCC does here. (And rounding a subnormal to 0 seems fine to me!)

Anyways, In C11 it is defined that the conversion from should be done "correctly rounded". And I'd tend to say that's what GCC does here; and the "should" gives leeway there, anyways. (And rounding a subnormal to 0 seems fine to me!)

added 2 characters in body
Source Link
Toby Speight
  • 32.3k
  • 58
  • 83
  • 118

iostream>>(float&) is specified to be functionally identical to std::use_facet(num_get), which itself is defined to be identical to strtof from <cstdlib>, which refers to the C11 standard, which …

iostream>>(float&) is specified to be functionally identical to std::use_facet(num_get), which itself is defined to be identical to strtof from , which refers to the C11 standard, which …

iostream>>(float&) is specified to be functionally identical to std::use_facet(num_get), which itself is defined to be identical to strtof from <cstdlib>, which refers to the C11 standard, which …

Source Link
Marcus Müller
  • 36.9k
  • 4
  • 59
  • 105

uff, so,

iostream>>(float&) is specified to be functionally identical to std::use_facet(num_get), which itself is defined to be identical to strtof from , which refers to the C11 standard, which …

Anyways, In C11 it is defined that the conversion is to be done "correctly rounded". And I'd tend to say that's what GCC does here. (And rounding a subnormal to 0 seems fine to me!)

But. Does it really matter? you will want to know when a number was too small to be represented sensibly. If I'm right with that assessment: use from_chars instead, make sure to check the error it sets for range errors. Here's a side-by-side comparison with your parse() function to highlight the different behaviours (Compiler Explorer):

#include <charconv> #include <iostream> #include <sstream> #include <string_view> void parse(const char* zstr) { std::istringstream s(zstr); float f; s >> f; std::cout << "parse: " << (bool)s; if (s) { std::cout << " (" << f << ")"; } std::cout << "\n"; } template <typename T> void parse_charconv(const std::string_view& sv) { T value; auto [first_fail, errorcode] = std::from_chars(sv.data(), sv.data() + sv.size(), value); constexpr std::errc noerror{}; std::cout << "charconv (" << typeid(T).name() << "): "; if (errorcode == noerror) { std::cout << "1 (" << value << ")"; } else if (errorcode == std::errc::invalid_argument) { std::cout << "i"; } else if (errorcode == std::errc::result_out_of_range) { std::cout << "R"; } else { std::cout << "?"; } std::cout << "\n"; } int main() { for (const char* str : {"1e-30", "1e-45", "1e-46", "banana pie"}) { std::cout << str << "\n"; parse(str); parse_charconv<float>(str); parse_charconv<double>(str); std::cout << "\n\n"; } }