diff --git a/include/boost/static_string/static_string.hpp b/include/boost/static_string/static_string.hpp index 7c7cc1b..05d1a02 100644 --- a/include/boost/static_string/static_string.hpp +++ b/include/boost/static_string/static_string.hpp @@ -472,15 +472,14 @@ to_static_string_float_impl(double value) noexcept char buffer[N + 1]; if (std::snprintf(buffer, N + 1, "%f", value) > N) { - const auto period = - std::char_traits::find(buffer, N, '.'); + // the + 4 is for the decimal, 'e', + // its sign, and the sign of the integral portion const int reserved_count = (std::max)(std::size_t(2), count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = N > reserved_count ? N - reserved_count : 0; - // we want at least 2 decimal places - if (!period || std::size_t(period - buffer) > N - 3) - std::snprintf(buffer, N + 1, "%.*e", precision, value); + // switch to scientific notation + std::snprintf(buffer, N + 1, "%.*e", precision, value); } // this will not throw return static_string(buffer); @@ -497,15 +496,14 @@ to_static_string_float_impl(long double value) noexcept // that would have been written if (std::snprintf(buffer, N + 1, "%Lf", value) > N) { - const auto period = - std::char_traits::find(buffer, N, '.'); + // the + 4 is for the decimal, 'e', + // its sign, and the sign of the integral portion const int reserved_count = (std::max)(std::size_t(2), count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = N > reserved_count ? N - reserved_count : 0; - // we want at least 2 decimal places - if (!period || std::size_t(period - buffer) > N - 3) - std::snprintf(buffer, N + 1, "%.*Le", precision, value); + // switch to scientific notation + std::snprintf(buffer, N + 1, "%.*Le", precision, value); } // this will not throw return static_string(buffer); @@ -522,15 +520,14 @@ to_static_wstring_float_impl(double value) noexcept // fit all the characters in the buffer if (std::swprintf(buffer, N + 1, L"%f", value) < 0) { - const auto period = - std::char_traits::find(buffer, N, '.'); + // the + 4 is for the decimal, 'e', + // its sign, and the sign of the integral portion const int reserved_count = (std::max)(std::size_t(2), count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = N > reserved_count ? N - reserved_count : 0; - // we want at least 2 decimal places - if (!period || std::size_t(period - buffer) > N - 3) - std::swprintf(buffer, N + 1, L"%.*e", precision, value); + // switch to scientific notation + std::swprintf(buffer, N + 1, L"%.*e", precision, value); } // this will not throw return static_wstring(buffer); @@ -547,15 +544,14 @@ to_static_wstring_float_impl(long double value) noexcept // fit all the characters in the buffer if (std::swprintf(buffer, N + 1, L"%Lf", value) < 0) { - const auto period = - std::char_traits::find(buffer, N, '.'); + // the + 4 is for the decimal, 'e', + // its sign, and the sign of the integral portion const int reserved_count = (std::max)(std::size_t(2), count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = N > reserved_count ? N - reserved_count : 0; - // we want at least 2 decimal places - if (!period || std::size_t(period - buffer) > N - 3) - std::swprintf(buffer, N + 1, L"%.*Le", precision, value); + // switch to scientific notation + std::swprintf(buffer, N + 1, L"%.*Le", precision, value); } // this will not throw return static_wstring(buffer); @@ -4589,6 +4585,15 @@ operator<<( // //------------------------------------------------------------------------------ +// Signed overloads have a + 2, one for the missing digit, +// and one for the sign. + +// Unsigned overloads have a + 1, for the missing digit. + +// Floating point overloads have a + 4, for the sign +// of the integral part, sign of the exponent, the 'e', +// and the decimal. + /// Converts `value` to a `static_string` static_string::digits10 + 2> inline @@ -4644,30 +4649,30 @@ to_static_string(unsigned long long value) noexcept } /// Converts `value` to a `static_string` -static_string::max_digits10 + 3> +static_string::max_digits10 + 4> inline to_static_string(float value) noexcept { return detail::to_static_string_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } /// Converts `value` to a `static_string` -static_string::max_digits10 + 3> +static_string::max_digits10 + 4> inline to_static_string(double value) noexcept { return detail::to_static_string_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } /// Converts `value` to a `static_string` -static_string::max_digits10 + 3> +static_string::max_digits10 + 4> inline to_static_string(long double value) noexcept { return detail::to_static_string_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } /// Converts `value` to a `static_wstring` @@ -4725,30 +4730,30 @@ to_static_wstring(unsigned long long value) noexcept } /// Converts `value` to a `static_wstring` -static_wstring::max_digits10 + 3> +static_wstring::max_digits10 + 4> inline to_static_wstring(float value) noexcept { return detail::to_static_wstring_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } /// Converts `value` to a `static_wstring` -static_wstring::max_digits10 + 3> +static_wstring::max_digits10 + 4> inline to_static_wstring(double value) noexcept { return detail::to_static_wstring_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } /// Converts `value` to a `static_wstring` -static_wstring::max_digits10 + 3> +static_wstring::max_digits10 + 4> inline to_static_wstring(long double value) noexcept { return detail::to_static_wstring_float_impl< - std::numeric_limits::max_digits10 + 3>(value); + std::numeric_limits::max_digits10 + 4>(value); } //------------------------------------------------------------------------------ diff --git a/test/static_string.cpp b/test/static_string.cpp index 9c14098..bf165cb 100644 --- a/test/static_string.cpp +++ b/test/static_string.cpp @@ -3713,34 +3713,32 @@ testToStaticString() { auto str = to_static_string(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); + static_string<0>::npos || str == "infinity" || str == "inf"); } { auto str = to_static_string(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); + static_string<0>::npos || str == "infinity" || str == "inf"); } { auto str = to_static_string(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); - std::cout << "3725: " << str << '\n'; + static_string<0>::npos || str == "infinity" || str == "inf"); } { auto str = to_static_wstring(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); + static_string<0>::npos || str == L"infinity" || str == L"inf"); } { auto str = to_static_wstring(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); + static_string<0>::npos || str == L"infinity" || str == L"inf"); } { auto str = to_static_wstring(std::numeric_limits::max()); BOOST_TEST(str.find('e') != static_string<0>::npos || str.find('.') != - static_string<0>::npos); - std::wcout << "3741: " << str << '\n'; + static_string<0>::npos || str == L"infinity" || str == L"inf"); } }