std::numeric_limits::max_digits10(3)

NAME
std::numeric_limits::max_digits10 - std::numeric_limits::max_digits10

Synopsis
   static constexpr int max_digits10 (since C++11)
   The value of std::numeric_limits<T>::max_digits10 is the number of base-10 digits
   that are necessary to uniquely represent all distinct values of the type T, such as
   necessary for serialization/deserialization to text. This constant is meaningful for
   all floating-point types.

Standard specializations
   T value of std::numeric_limits<T>::max_digits10
   /* non-specialized */ 0
   (C++11)
   bool (C++11) 0
   char (C++11) 0
   signed char (C++11) 0
   unsigned char (C++11) 0
   wchar_t (C++11) 0
   char8_t (C++20) 0
   char16_t (C++11) 0
   char32_t (C++11) 0
   short (C++11) 0
   unsigned short (C++11) 0
   int (C++11) 0
   unsigned int (C++11) 0
   long (C++11) 0
   unsigned long (C++11) 0
   long long (C++11) 0
   unsigned long long 0
   (C++11)
                        FLT_DECIMAL_DIG or
   float (C++11) std::ceil(std::numeric_limits<float>::digits * std::log10(2)
                        + 1)
                        DBL_DECIMAL_DIG
   double (C++11) orstd::ceil(std::numeric_limits<double>::digits *
                        std::log10(2) + 1)
                        DECIMAL_DIG or LDBL_DECIMAL_DIG
   long double (C++11) orstd::ceil(std::numeric_limits<long double>::digits *
                        std::log10(2) + 1)

Notes
   Unlike most mathematical operations, the conversion of a floating-point value to
   text and back is exact as long as at least max_digits10 were used (9 for float, 17
   for double): it is guaranteed to produce the same floating-point value, even though
   the intermediate text representation is not exact. It may take over a hundred
   decimal digits to represent the precise value of a float in decimal notation.

Example
// Run this code
 #include <limits>
 #include <sstream>
 #include <iomanip>
 #include <cmath>
 #include <iostream>
 int main()
 {
     float value = 10.0000086;
     constexpr auto digits10 = std::numeric_limits<decltype(value)>::digits10;
     constexpr auto max_digits10 = std::numeric_limits<decltype(value)>::max_digits10;
     constexpr auto submax_digits10 = max_digits10 - 1;
     std::cout
         << "float:\n"
         << " digits10 is " << digits10 << " digits" << '\n'
         << " max_digits10 is " << max_digits10 << " digits" << '\n'
         << "submax_digits10 is " << submax_digits10 << " digits" << '\n'
         << '\n';
     const auto original_precision = std::cout.precision();
     for( auto i = 0; i < 5; ++i )
     {
         std::cout
             << " max_digits10: " << std::setprecision(max_digits10) << value << '\n'
             << "submax_digits10: " << std::setprecision(submax_digits10) << value << '\n'
             << '\n';
         value = std::nextafter( value, std::numeric_limits<decltype(value)>::max() );
     }
     std::cout.precision( original_precision );
     return 0;
 }

Output:
 float:
        digits10 is 6 digits
    max_digits10 is 9 digits
 submax_digits10 is 8 digits
    max_digits10: 10.0000086
 submax_digits10: 10.000009
    max_digits10: 10.0000095
 submax_digits10: 10.00001
    max_digits10: 10.0000105
 submax_digits10: 10.00001
    max_digits10: 10.0000114
 submax_digits10: 10.000011
    max_digits10: 10.0000124
 submax_digits10: 10.000012

See also
   radix the radix or integer base used by the representation of the given type
   [static] (public static member constant)
   digits number of radix digits that can be represented without change
   [static] (public static member constant)
   digits10 number of decimal digits that can be represented without change
   [static] (public static member constant)
   min_exponent one more than the smallest negative power of the radix that is a valid
   [static] normalized floating-point value
                (public static member constant)
   max_exponent one more than the largest integer power of the radix that is a valid
   [static] finite floating-point value
                (public static member constant)