13inline uint64_t Writer::RoundScaledF32(
float value, uint32_t scale)
15 uint32_t bits = std::bit_cast<uint32_t>(value);
16 uint32_t exponent_bits = (bits >> 23) & 0xFFU;
17 uint32_t fraction_bits = bits & 0x7FFFFFU;
18 uint32_t significand =
19 (exponent_bits == 0) ? fraction_bits : ((1U << 23) | fraction_bits);
21 (exponent_bits == 0) ? -149 :
static_cast<int>(exponent_bits) - 150;
22 uint64_t numerator =
static_cast<uint64_t
>(significand) * scale;
26 return numerator << exponent2;
29 unsigned int shift =
static_cast<unsigned int>(-exponent2);
34 uint64_t quotient = numerator >> shift;
35 uint64_t remainder = numerator & ((uint64_t{1} << shift) - 1U);
36 uint64_t halfway = uint64_t{1} << (shift - 1);
37 if (remainder > halfway || (remainder == halfway && (quotient & 1U) != 0U))
48template <
typename Float>
61template <
typename Float>
62Float Writer::Power10(
int exponent)
66 unsigned int remaining =
67 static_cast<unsigned int>(exponent < 0 ? -exponent : exponent);
69 while (remaining != 0)
71 if ((remaining & 1U) != 0U)
100template <
typename Float>
103 DecimalScale<Float> normalized{};
109 int binary_exponent = 0;
110 std::frexp(value, &binary_exponent);
111 constexpr Float log10_of_2 =
112 static_cast<Float
>(0.30102999566398119521373889472449L);
113 normalized.exponent =
114 static_cast<int>(
static_cast<Float
>(binary_exponent - 1) * log10_of_2);
115 normalized.scale = Power10<Float>(normalized.exponent);
117 Float scaled = value / normalized.scale;
120 normalized.scale /= 10;
121 --normalized.exponent;
126 normalized.scale *= 10;
127 ++normalized.exponent;
142template <
typename Float>
143uint8_t Writer::ExtractDigit(Float& value, Float scale)
145 Float scaled = value / scale;
146 auto digit =
static_cast<int>(scaled +
static_cast<Float
>(1e-12L));
156 value -=
static_cast<Float
>(digit) * scale;
157 Float epsilon = scale *
static_cast<Float
>(1e-9L);
158 if (value < 0 && value > -epsilon)
163 return static_cast<uint8_t
>(digit);
172inline size_t Writer::TrimGeneralText(
char* text,
size_t size)
174 size_t exponent_pos = size;
175 for (
size_t i = 0; i < size; ++i)
177 if (text[i] ==
'e' || text[i] ==
'E')
184 size_t mantissa_end = exponent_pos;
185 while (mantissa_end > 0 && text[mantissa_end - 1] ==
'0')
189 if (mantissa_end > 0 && text[mantissa_end - 1] ==
'.')
194 if (exponent_pos == size)
199 std::memmove(text + mantissa_end, text + exponent_pos, size - exponent_pos);
200 return mantissa_end + (size - exponent_pos);
211inline bool Writer::AppendExponentText(
char* out,
size_t& out_size,
int exponent,
214 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
215 upper_case ?
'E' :
'e'))
219 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
220 exponent < 0 ?
'-' :
'+'))
225 char digits[UnsignedDigitCapacity<unsigned int, 10>()];
226 unsigned int magnitude =
227 static_cast<unsigned int>(exponent < 0 ? -exponent : exponent);
228 size_t digit_count = AppendUnsigned<10>(digits, magnitude);
229 if (digit_count < 2 &&
230 !AppendBufferChar(out, float_buffer_capacity, out_size,
'0'))
235 return AppendBufferText(out, float_buffer_capacity, out_size,
236 std::string_view(digits, digit_count));
浮点文本输出归一化过程中使用的十进制缩放对 / Decimal-scale pair used while normalizing one float for text output.
Float scale
10 ^ exponent / 10 的 exponent 次幂
int exponent
decimal exponent / 十进制指数