diff --git a/include/boost/charconv/detail/dragonbox/floff.hpp b/include/boost/charconv/detail/dragonbox/floff.hpp index 6ac0031..3652b50 100644 --- a/include/boost/charconv/detail/dragonbox/floff.hpp +++ b/include/boost/charconv/detail/dragonbox/floff.hpp @@ -1333,6 +1333,7 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision, auto buffer_size = static_cast(last - first); auto buffer = first; + bool trailing_zeros_removed = false; BOOST_CHARCONV_ASSERT(precision >= 0); using namespace detail; @@ -3849,6 +3850,7 @@ insert_decimal_dot: } // Remove trailing zeros. + trailing_zeros_removed = true; while (true) { auto prev = buffer - 1; @@ -3903,7 +3905,16 @@ insert_decimal_dot: print_2_digits(static_cast(decimal_exponent_normalized), buffer); buffer += 2; } - } + } + else if (!trailing_zeros_removed && buffer - (decimal_dot_pos + 1) < precision) + { + // If we have fixed precision, and we don't have enough digits after the decimal yet + // insert a sufficient amount of zeros + const auto remaining_zeros = precision - (buffer - (decimal_dot_pos + 1)); + BOOST_CHARCONV_ASSERT(remaining_zeros > 0); + std::memset(buffer, '0', static_cast(remaining_zeros)); + buffer += remaining_zeros; + } return {buffer, std::errc()}; diff --git a/test/Jamfile b/test/Jamfile index 655d52d..3700ad9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -70,4 +70,5 @@ run github_issue_166.cpp ; run github_issue_166_float128.cpp ; run github_issue_186.cpp ; run github_issue_212.cpp ; +run github_issue_266.cpp ; run github_issue_267.cpp ; diff --git a/test/github_issue_266.cpp b/test/github_issue_266.cpp new file mode 100644 index 0000000..90c99f8 --- /dev/null +++ b/test/github_issue_266.cpp @@ -0,0 +1,35 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// See: https://github.com/boostorg/charconv/issues/266 + +#include +#include + +template +void test(T value, int precision, const char* correct_result) +{ + char buffer[64] {}; + const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, precision); + BOOST_TEST_CSTR_EQ(buffer, correct_result); + BOOST_TEST(r); +} + +int main() +{ + test(123456789012345.6789012345678901, 5, "123456789012345.67188"); + test(1234567890123456.789012345678901, 5, "1234567890123456.75000"); + test(12345678901234567.89012345678901, 5, "12345678901234568.00000"); + test(123456789012345678.9012345678901, 5, "123456789012345680.00000"); + test(1234567890123456789.012345678901, 5, "1234567890123456768.00000"); + + test(123456789012345678901234567.8901, 5, "123456789012345678152597504.00000"); + test(12345678901234567890123456.78901, 5, "12345678901234568244756480.00000"); + test(1234567890123456789012345.678901, 5, "1234567890123456824475648.00000"); + test(123456789012345678901234.5678901, 5, "123456789012345685803008.00000"); + test(12345678901234567890123.45678901, 5, "12345678901234567741440.00000"); + test(123456789012345678901.2345678901, 5, "123456789012345683968.00000"); + + return boost::report_errors(); +}