@@ -109,11 +109,15 @@ constexpr std::size_t min_exp_digits = 2u;
109
109
}
110
110
111
111
[[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:
112
115
// +1 for fractional separator '.'
113
116
// +1 for exponent separator 'e'
114
117
// +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 ;
117
121
}
118
122
119
123
constexpr 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 {
164
168
165
169
[[nodiscard]] constexpr bool append_constexpr (small_string_span ss, signed_fixed_data fd) noexcept {
166
170
// Statically allocate enough space for the biggest float,
167
- // then resize to the length of this particular float.
168
171
small_string<max_float_length> tmp;
169
- tmp.resize (num_digits (fd));
170
172
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 ));
172
178
173
179
// The exponent has a fixed size, so we can start by writing the main digits.
174
180
// We write the digits with always a single digit before the decimal separator,
175
181
// and the rest as fractional part. This will require adjusting the value of
176
182
// 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) {
180
185
if (j < 10u ) {
181
186
tmp[tmp.size () - k] = ' .' ;
182
187
++k;
@@ -191,7 +196,10 @@ set_precision(signed_fixed_data fd, std::size_t p) noexcept {
191
196
192
197
// Now write the exponent, adjusted for the chosen display (one digit before the decimal
193
198
// 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 );
195
203
196
204
k = 1 ;
197
205
for (fixed_exp_t j = exponent > 0 ? exponent : -exponent; j != 0 ; j /= 10 , ++k) {
0 commit comments