@@ -109,11 +109,15 @@ constexpr std::size_t min_exp_digits = 2u;
109109}
110110
111111[[nodiscard]] constexpr std::size_t num_digits (const signed_fixed_data& x) noexcept {
112+ // Don't forget to modify the stored exponent by the number of stored digits, since we always
113+ // print floating point numbers as 1.23456 but store them as 123456.
114+ // Why +3:
112115 // +1 for fractional separator '.'
113116 // +1 for exponent separator 'e'
114117 // +1 for exponent sign
115- return num_digits<10 >(static_cast <large_uint_t >(x.digits )) + num_exp_digits (x.exponent ) +
116- (x.sign ? 1u : 0u ) + 3u ;
118+ const std::size_t stored_digits = num_digits<10 >(static_cast <large_uint_t >(x.digits ));
119+ return stored_digits + (x.sign ? 1u : 0u ) +
120+ num_exp_digits (static_cast <fixed_exp_t >(x.exponent + stored_digits - 1 )) + 3u ;
117121}
118122
119123constexpr std::size_t max_float_length = num_digits(signed_fixed_data{
@@ -164,19 +168,20 @@ set_precision(signed_fixed_data fd, std::size_t p) noexcept {
164168
165169[[nodiscard]] constexpr bool append_constexpr (small_string_span ss, signed_fixed_data fd) noexcept {
166170 // Statically allocate enough space for the biggest float,
167- // then resize to the length of this particular float.
168171 small_string<max_float_length> tmp;
169- tmp.resize (num_digits (fd));
170172
171- const std::size_t exp_digits = num_exp_digits (fd.exponent );
173+ // Resize to fit the digits (without exponent part).
174+ // +1 for fractional separator '.'
175+ // +1 for sign
176+ const std::size_t stored_digits = num_digits<10 >(static_cast <large_uint_t >(fd.digits ));
177+ tmp.resize (stored_digits + 1u + (fd.sign ? 1u : 0u ));
172178
173179 // The exponent has a fixed size, so we can start by writing the main digits.
174180 // We write the digits with always a single digit before the decimal separator,
175181 // and the rest as fractional part. This will require adjusting the value of
176182 // the exponent later.
177- std::size_t k = 3u + exp_digits;
178- fixed_exp_t exponent_add = 0 ;
179- for (fixed_digits_t j = fd.digits ; j != 0u ; j /= 10u , ++k, ++exponent_add) {
183+ std::size_t k = 1u ;
184+ for (fixed_digits_t j = fd.digits ; j != 0u ; j /= 10u , ++k) {
180185 if (j < 10u ) {
181186 tmp[tmp.size () - k] = ' .' ;
182187 ++k;
@@ -191,7 +196,10 @@ set_precision(signed_fixed_data fd, std::size_t p) noexcept {
191196
192197 // Now write the exponent, adjusted for the chosen display (one digit before the decimal
193198 // separator).
194- const fixed_exp_t exponent = fd.exponent + exponent_add - 1 ;
199+ const fixed_exp_t exponent = static_cast <fixed_exp_t >(fd.exponent + stored_digits - 1 );
200+
201+ // Allocate space for it, +1 for 'e', and +1 for exponent sign.
202+ tmp.grow (num_exp_digits (exponent) + 2u );
195203
196204 k = 1 ;
197205 for (fixed_exp_t j = exponent > 0 ? exponent : -exponent; j != 0 ; j /= 10 , ++k) {
0 commit comments