1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
/*!

Floating-point number to decimal conversion routines.

# Problem statement

We are given the floating-point number `v = f * 2^e` with an integer `f`,
and its bounds `minus` and `plus` such that any number between `v - minus` and
`v + plus` will be rounded to `v`. For the simplicity we assume that
this range is exclusive. Then we would like to get the unique decimal
representation `V = 0.d[0..n-1] * 10^k` such that:

- `d[0]` is non-zero.

- It's correctly rounded when parsed back: `v - minus < V < v + plus`.
  Furthermore it is shortest such one, i.e., there is no representation
  with less than `n` digits that is correctly rounded.

- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that
  there might be two representations satisfying this uniqueness requirement,
  in which case some tie-breaking mechanism is used.

We will call this mode of operation as to the *shortest* mode. This mode is used
when there is no additional constraint, and can be thought as a "natural" mode
as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1").

We have two more modes of operation closely related to each other. In these modes
we are given either the number of significant digits `n` or the last-digit
limitation `limit` (which determines the actual `n`), and we would like to get
the representation `V = 0.d[0..n-1] * 10^k` such that:

- `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned.

- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again,
  there might be some tie-breaking mechanism.

When `limit` is given but not `n`, we set `n` such that `k - n = limit`
so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`.
If such `n` is negative, we clip it to zero so that we will only get `k`.
We are also limited by the supplied buffer. This limitation is used to print
the number up to given number of fractional digits without knowing
the correct `k` beforehand.

We will call the mode of operation requiring `n` as to the *exact* mode,
and one requiring `limit` as to the *fixed* mode. The exact mode is a subset of
the fixed mode: the sufficiently large last-digit limitation will eventually fill
the supplied buffer and let the algorithm to return.

# Implementation overview

It is easy to get the floating point printing correct but slow (Russ Cox has
[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but
fast (naïve division and modulo). But it is surprisingly hard to print
floating point numbers correctly *and* efficiently.

There are two classes of algorithms widely known to be correct.

- The "Dragon" family of algorithm is first described by Guy L. Steele Jr. and
  Jon L. White. They rely on the fixed-size big integer for their correctness.
  A slight improvement was found later, which is posthumously described by
  Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is
  a popular implementation of this strategy.

- The "Grisu" family of algorithm is first described by Florian Loitsch.
  They use very cheap integer-only procedure to determine the close-to-correct
  representation which is at least guaranteed to be shortest. The variant,
  Grisu3, actively detects if the resulting representation is incorrect.

We implement both algorithms with necessary tweaks to suit our requirements.
In particular, published literatures are short of the actual implementation
difficulties like how to avoid arithmetic overflows. Each implementation,
available in `strategy::dragon` and `strategy::grisu` respectively,
extensively describes all necessary justifications and many proofs for them.
(It is still difficult to follow though. You have been warned.)

Both implementations expose two public functions:

- `format_shortest(decoded, buf)`, which always needs at least
  `MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode.

- `format_exact(decoded, buf, limit)`, which accepts as small as
  one digit of buffer. Implements exact and fixed modes.

They try to fill the `u8` buffer with digits and returns the number of digits
written and the exponent `k`. They are total for all finite `f32` and `f64`
inputs (Grisu internally falls back to Dragon if necessary).

The rendered digits are formatted into the actual string form with
four functions:

- `to_shortest_str` prints the shortest representation, which can be padded by
  zeroes to make *at least* given number of fractional digits.

- `to_shortest_exp_str` prints the shortest representation, which can be
  padded by zeroes when its exponent is in the specified ranges,
  or can be printed in the exponential form such as `1.23e45`.

- `to_exact_exp_str` prints the exact representation with given number of
  digits in the exponential form.

- `to_exact_fixed_str` prints the fixed representation with *exactly*
  given number of fractional digits.

They all return a slice of preallocated `Part` array, which corresponds to
the individual part of strings: a fixed string, a part of rendered digits,
a number of zeroes or a small (`u16`) number. The caller is expected to
provide a large enough buffer and `Part` array, and to assemble the final
string from resulting `Part`s itself.

All algorithms and formatting functions are accompanied by extensive tests
in `coretests::num::flt2dec` module. It also shows how to use individual
functions.

*/

// 尽管对此进行了广泛记录,但原则上是私有的,仅对测试公开。
// 不要暴露我们。
#![doc(hidden)]
#![unstable(
    feature = "flt2dec",
    reason = "internal routines only exposed for testing",
    issue = "none"
)]

pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};

use super::fmt::{Formatted, Part};
use crate::mem::MaybeUninit;

pub mod decoder;
pub mod estimator;

/// 数字生成算法。
pub mod strategy {
    pub mod dragon;
    pub mod grisu;
}

/// 最短模式所需的最小缓冲区大小。
///
/// 导出它并不是一件容易的事,但这是一个加格式运算结果最短的有效十进制数字的最大数目。
///
/// 确切的公式是 `ceil(# bits in mantissa * log_10 2 + 1)`。
pub const MAX_SIG_DIGITS: usize = 17;

/// 当 `d` 包含十进制数字时,增加最后一位数字并传播进位。
/// 当它导致长度改变时,返回下一个数字。
#[doc(hidden)]
pub fn round_up(d: &mut [u8]) -> Option<u8> {
    match d.iter().rposition(|&c| c != b'9') {
        Some(i) => {
            // d[i+1..n] 都是 9
            d[i] += 1;
            for j in i + 1..d.len() {
                d[j] = b'0';
            }
            None
        }
        None if d.len() > 0 => {
            // 999..999 四舍五入到 1000..000 并增加指数
            d[0] = b'1';
            for j in 1..d.len() {
                d[j] = b'0';
            }
            Some(b'0')
        }
        None => {
            // 空缓冲区向上取整 (有点奇怪但合理)
            Some(b'1')
        }
    }
}

/// 将给定的十进制数字 `0.<...buf...> * 10^exp` 格式化为至少具有给定数目的小数位数的十进制格式。
///
/// 结果存储到提供的部分数组中,并返回写入部分的切片。
///
/// `frac_digits` 可以小于 `buf` 中实际小数位数;
/// 它将被忽略并且将打印全数字。它仅用于在渲染的数字后打印其他零。
/// 因此,`frac_digits` 为 0 意味着它将仅打印给定的数字,而不会打印其他任何内容。
///
fn digits_to_dec_str<'a>(
    buf: &'a [u8],
    exp: i16,
    frac_digits: usize,
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> &'a [Part<'a>] {
    assert!(!buf.is_empty());
    assert!(buf[0] > b'0');
    assert!(parts.len() >= 4);

    // 如果对最后一位的位置有限制,则假定 `buf` 左填充虚拟零。
    // 虚拟零的数量 `nzeroes` 等于 `max(0, exp + frac_digits - buf.len())`,因此最后一位 `exp - buf.len() - nzeroes` 的位置不超过 `-frac_digits`:
    //
    //
    //                       |<-virtual->|
    //       |<---- buf ---->|  zeroes   |     exp
    //    0. 1 2 3 4 5 6 7 8 9 _ _ _ _ _ _ x 10
    //    |                  |           |
    // 10^exp    10^(exp-buf.len())   10^(exp-buf.len()-nzeroes)
    //
    // `nzeroes` 是针对每种情况单独计算的,以避免溢出。
    //

    if exp <= 0 {
        // 小数点在呈现数字之前: [0.][000...000][1234][____]
        let minus_exp = -(exp as i32) as usize;
        parts[0] = MaybeUninit::new(Part::Copy(b"0."));
        parts[1] = MaybeUninit::new(Part::Zero(minus_exp));
        parts[2] = MaybeUninit::new(Part::Copy(buf));
        if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp {
            parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp));
            // SAFETY: 我们刚刚初始化了元素 `..4`。
            unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
        } else {
            // SAFETY: 我们刚刚初始化了元素 `..3`。
            unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
        }
    } else {
        let exp = exp as usize;
        if exp < buf.len() {
            // 小数点在呈现的数字内: [12][.][34][____]
            parts[0] = MaybeUninit::new(Part::Copy(&buf[..exp]));
            parts[1] = MaybeUninit::new(Part::Copy(b"."));
            parts[2] = MaybeUninit::new(Part::Copy(&buf[exp..]));
            if frac_digits > buf.len() - exp {
                parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp)));
                // SAFETY: 我们刚刚初始化了元素 `..4`。
                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
            } else {
                // SAFETY: 我们刚刚初始化了元素 `..3`。
                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
            }
        } else {
            // 小数点位于显示的数字之后: [1234][____0000] 或者 [1234][__][.][__]。
            parts[0] = MaybeUninit::new(Part::Copy(buf));
            parts[1] = MaybeUninit::new(Part::Zero(exp - buf.len()));
            if frac_digits > 0 {
                parts[2] = MaybeUninit::new(Part::Copy(b"."));
                parts[3] = MaybeUninit::new(Part::Zero(frac_digits));
                // SAFETY: 我们刚刚初始化了元素 `..4`。
                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
            } else {
                // SAFETY: 我们刚刚初始化了元素 `..2`。
                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }
            }
        }
    }
}

/// 将给定的十进制数字 `0.<...buf...> * 10^exp` 格式化为至少具有给定数量的有效数字的指数形式。
///
/// 当 `upper` 为 `true` 时,指数将以 `E` 为前缀; 否则就是 `e`。
/// 结果存储到提供的部分数组中,并返回写入部分的切片。
///
/// `min_digits` 可以小于 `buf` 中的实际有效位数;
/// 它将被忽略并且将打印全数字。它仅用于在渲染的数字后打印其他零。
/// 因此,`min_digits == 0` 意味着它将仅打印给定的数字,而不会打印其他任何内容。
///
fn digits_to_exp_str<'a>(
    buf: &'a [u8],
    exp: i16,
    min_ndigits: usize,
    upper: bool,
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> &'a [Part<'a>] {
    assert!(!buf.is_empty());
    assert!(buf[0] > b'0');
    assert!(parts.len() >= 6);

    let mut n = 0;

    parts[n] = MaybeUninit::new(Part::Copy(&buf[..1]));
    n += 1;

    if buf.len() > 1 || min_ndigits > 1 {
        parts[n] = MaybeUninit::new(Part::Copy(b"."));
        parts[n + 1] = MaybeUninit::new(Part::Copy(&buf[1..]));
        n += 2;
        if min_ndigits > buf.len() {
            parts[n] = MaybeUninit::new(Part::Zero(min_ndigits - buf.len()));
            n += 1;
        }
    }

    // 0.1234 x 10^exp = 1.234 x 10^(exp-1)
    let exp = exp as i32 - 1; // 当 exp 为 i16::MIN 时避免下溢
    if exp < 0 {
        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E-" } else { b"e-" }));
        parts[n + 1] = MaybeUninit::new(Part::Num(-exp as u16));
    } else {
        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E" } else { b"e" }));
        parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
    }
    // SAFETY: 我们刚刚初始化了元素 `..n + 2`。
    unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) }
}

/// 标志格式设置选项。
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sign {
    /// 为任何负值打印 `-`。
    Minus, // -inf -1 -0  0  1  inf nan
    /// 为任何负值打印 `-`,否则打印 `+`。
    MinusPlus, // -inf -1 -0 +0 +1 +inf nan
}

/// 返回与要格式化的符号对应的静态字节字符串。
/// 它可以是 `""`,`"+"` 或 `"-"`。
fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str {
    match (*decoded, sign) {
        (FullDecoded::Nan, _) => "",
        (_, Sign::Minus) => {
            if negative {
                "-"
            } else {
                ""
            }
        }
        (_, Sign::MinusPlus) => {
            if negative {
                "-"
            } else {
                "+"
            }
        }
    }
}

/// 将给定的浮点数格式化为至少具有给定数目的小数位数的十进制形式。
/// 将结果存储到提供的零件阵列中,同时利用给定的字节缓冲区作为暂存器。
/// `upper` 当前未使用,但留给 future 决定更改非有限值的情况,即 `inf` 和 `nan`。
///
/// 要渲染的第一部分始终是 `Part::Sign` (如果未渲染任何符号,则可以为空字符串)。
///
/// `format_shortest` 应该是底层的数字生成函数。
/// 它应该返回它初始化的缓冲区的一部分。
/// 您可能需要 `strategy::grisu::format_shortest`。
///
/// `frac_digits` 可以小于 `v` 中实际小数位数;
/// 它将被忽略并且将打印全数字。它仅用于在渲染的数字后打印其他零。
/// 因此,`frac_digits` 为 0 意味着它将仅打印给定的数字,而不会打印其他任何内容。
///
/// 字节缓冲区的长度至少应为 `MAX_SIG_DIGITS` 字节。
/// 由于最坏的情况,例如 `[+][0.][0000][2][0000]` 和 `frac_digits = 10`,应该至少有 4 个零件可用。
///
///
///
pub fn to_shortest_str<'a, T, F>(
    mut format_shortest: F,
    v: T,
    sign: Sign,
    frac_digits: usize,
    buf: &'a mut [MaybeUninit<u8>],
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> Formatted<'a>
where
    T: DecodableFloat,
    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
{
    assert!(parts.len() >= 4);
    assert!(buf.len() >= MAX_SIG_DIGITS);

    let (negative, full_decoded) = decode(v);
    let sign = determine_sign(sign, &full_decoded, negative);
    match full_decoded {
        FullDecoded::Nan => {
            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Infinite => {
            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Zero => {
            if frac_digits > 0 {
                // [0.][0000]
                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..2`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
                }
            } else {
                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..1`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
                }
            }
        }
        FullDecoded::Finite(ref decoded) => {
            let (buf, exp) = format_shortest(decoded, buf);
            Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
        }
    }
}

/// 根据所得的指数,将给定的浮点数格式化为十进制形式或指数形式。
/// 将结果存储到提供的零件阵列中,同时利用给定的字节缓冲区作为暂存器。
/// `upper` 用于确定非有限值的情况 (`inf` 和 `nan`) 或指数前缀的情况 (`e` 或 `E`)。
/// 要渲染的第一部分始终是 `Part::Sign` (如果未渲染任何符号,则可以为空字符串)。
///
/// `format_shortest` 应该是底层的数字生成函数。
/// 它应该返回它初始化的缓冲区的一部分。
/// 您可能需要 `strategy::grisu::format_shortest`。
///
/// `dec_bounds` 是元组 `(lo, hi)`,因此仅当 `10^lo <= V < 10^hi` 时,数字格式设置为十进制。
/// 请注意,这是 *表观*`V`,而不是实际的 `v`! 因此,任何以指数形式打印的指数都不能在此范围内,从而避免混淆。
///
///
/// 字节缓冲区的长度至少应为 `MAX_SIG_DIGITS` 字节。
/// 由于最坏的情况,例如 `[+][1][.][2345][e][-][6]`,应该至少有 6 个零件可用。
///
///
///
///
///
pub fn to_shortest_exp_str<'a, T, F>(
    mut format_shortest: F,
    v: T,
    sign: Sign,
    dec_bounds: (i16, i16),
    upper: bool,
    buf: &'a mut [MaybeUninit<u8>],
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> Formatted<'a>
where
    T: DecodableFloat,
    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
{
    assert!(parts.len() >= 6);
    assert!(buf.len() >= MAX_SIG_DIGITS);
    assert!(dec_bounds.0 <= dec_bounds.1);

    let (negative, full_decoded) = decode(v);
    let sign = determine_sign(sign, &full_decoded, negative);
    match full_decoded {
        FullDecoded::Nan => {
            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Infinite => {
            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Zero => {
            parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
                MaybeUninit::new(Part::Copy(b"0"))
            } else {
                MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
            };
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Finite(ref decoded) => {
            let (buf, exp) = format_shortest(decoded, buf);
            let vis_exp = exp as i32 - 1;
            let parts = if dec_bounds.0 as i32 <= vis_exp && vis_exp < dec_bounds.1 as i32 {
                digits_to_dec_str(buf, exp, 0, parts)
            } else {
                digits_to_exp_str(buf, exp, 0, upper, parts)
            };
            Formatted { sign, parts }
        }
    }
}

/// 对于从给定的解码指数计算出的最大缓冲区大小,返回一个相当粗略的近似值 (上限)。
///
/// 确切的限制是:
///
/// - 当为 `exp < 0` 时,最大长度为 `ceil(log_10 (5^-exp * (2^64 - 1)))`。
/// - 当为 `exp >= 0` 时,最大长度为 `ceil(log_10 (2^exp * (2^64 - 1)))`。
///
/// `ceil(log_10 (x^exp * (2^64 - 1)))` 小于 `ceil(log_10 (2^64 - 1)) + ceil(exp * log_10 x)`,而 `ceil(log_10 (2^64 - 1)) + ceil(exp * log_10 x)` 又小于 `20 + (1 + exp * log_10 x)`。
/// 我们使用 `log_10 2 < 5/16` 和 `log_10 5 < 12/16` 这样的事实,足以满足我们的目的。
///
/// 我们为什么需要这个? `format_exact` 函数将填充整个缓冲区,除非受最后一位数字的限制,但所请求的位数可能非常大 (例如 30,000 位)。
///
/// 绝大多数缓冲区将填充零,因此我们不想预先分配所有缓冲区。
/// 因此,对于任何给定的参数,
/// `f64` 的 826 字节缓冲区应该足够。将其与最坏情况下的实际数字进行比较: 770 字节 (当 `exp = -1074` 时)。
///
///
///
///
///
fn estimate_max_buf_len(exp: i16) -> usize {
    21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4)
}

/// 将给定的浮点数格式化为具有给定的有效位数的指数形式。
/// 将结果存储到提供的零件阵列中,同时利用给定的字节缓冲区作为暂存器。
/// `upper` 用于确定指数前缀 (`e` 或 `E`) 的大小写。
/// 要渲染的第一部分始终是 `Part::Sign` (如果未渲染任何符号,则可以为空字符串)。
///
/// `format_exact` 应该是底层的数字生成函数。
/// 它应该返回它初始化的缓冲区的一部分。
/// 您可能需要 `strategy::grisu::format_exact`。
///
/// 字节缓冲区的长度至少应为 `ndigits` 字节,除非 `ndigits` 太大,以至于只能写入固定数量的数字。
/// (`f64` 的临界点大约为 800,因此 1000 字节应该足够。) 由于最坏的情况 (例如 `[+][1][.][2345][e][-][6]`),因此至少应有 6 个可用部分。
///
///
///
///
///
pub fn to_exact_exp_str<'a, T, F>(
    mut format_exact: F,
    v: T,
    sign: Sign,
    ndigits: usize,
    upper: bool,
    buf: &'a mut [MaybeUninit<u8>],
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> Formatted<'a>
where
    T: DecodableFloat,
    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
{
    assert!(parts.len() >= 6);
    assert!(ndigits > 0);

    let (negative, full_decoded) = decode(v);
    let sign = determine_sign(sign, &full_decoded, negative);
    match full_decoded {
        FullDecoded::Nan => {
            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Infinite => {
            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Zero => {
            if ndigits > 1 {
                // [0.][0000][e0]
                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
                parts[1] = MaybeUninit::new(Part::Zero(ndigits - 1));
                parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" }));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..3`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) },
                }
            } else {
                parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..1`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
                }
            }
        }
        FullDecoded::Finite(ref decoded) => {
            let maxlen = estimate_max_buf_len(decoded.exp);
            assert!(buf.len() >= ndigits || buf.len() >= maxlen);

            let trunc = if ndigits < maxlen { ndigits } else { maxlen };
            let (buf, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
            Formatted { sign, parts: digits_to_exp_str(buf, exp, ndigits, upper, parts) }
        }
    }
}

/// 将给定的浮点数格式转换为十进制形式,并精确给出小数位数。
/// 将结果存储到提供的零件阵列中,同时利用给定的字节缓冲区作为暂存器。
/// `upper` 当前未使用,但留给 future 决定更改非有限值的情况,即 `inf` 和 `nan`。
/// 要渲染的第一部分始终是 `Part::Sign` (如果未渲染任何符号,则可以为空字符串)。
///
/// `format_exact` 应该是底层的数字生成函数。
/// 它应该返回它初始化的缓冲区的一部分。
/// 您可能需要 `strategy::grisu::format_exact`。
///
/// 除非 `frac_digits` 太大以至于只能写入固定的位数,否则字节缓冲区应该足以用于输出。
/// (`f64` 的临界点大约为 800,并且 1000 字节应该足够。) 由于最坏的情况,例如 `[+][0.][0000][2][0000]` 和 `frac_digits = 10`,应该至少有 4 个可用部分。
///
///
///
///
///
pub fn to_exact_fixed_str<'a, T, F>(
    mut format_exact: F,
    v: T,
    sign: Sign,
    frac_digits: usize,
    buf: &'a mut [MaybeUninit<u8>],
    parts: &'a mut [MaybeUninit<Part<'a>>],
) -> Formatted<'a>
where
    T: DecodableFloat,
    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
{
    assert!(parts.len() >= 4);

    let (negative, full_decoded) = decode(v);
    let sign = determine_sign(sign, &full_decoded, negative);
    match full_decoded {
        FullDecoded::Nan => {
            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Infinite => {
            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
            // SAFETY: 我们刚刚初始化了元素 `..1`。
            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
        }
        FullDecoded::Zero => {
            if frac_digits > 0 {
                // [0.][0000]
                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..2`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
                }
            } else {
                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                Formatted {
                    sign,
                    // SAFETY: 我们刚刚初始化了元素 `..1`。
                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
                }
            }
        }
        FullDecoded::Finite(ref decoded) => {
            let maxlen = estimate_max_buf_len(decoded.exp);
            assert!(buf.len() >= maxlen);

            // `frac_digits` 可能非常大。
            // 在这种情况下,`format_exact` 将更早地结束渲染数字,因为我们受到 `maxlen` 的严格限制。
            //
            let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN };
            let (buf, exp) = format_exact(decoded, &mut buf[..maxlen], limit);
            if exp <= limit {
                // 该限制无法满足,因此无论 `exp` 为何,该值都应呈现为零。
                // 这不包括仅在最后四舍五入后才达到限制的情况; 这是 `exp = limit + 1` 的常规情况。
                //
                debug_assert_eq!(buf.len(), 0);
                if frac_digits > 0 {
                    // [0.][0000]
                    parts[0] = MaybeUninit::new(Part::Copy(b"0."));
                    parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
                    Formatted {
                        sign,
                        // SAFETY: 我们刚刚初始化了元素 `..2`。
                        parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
                    }
                } else {
                    parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                    Formatted {
                        sign,
                        // SAFETY: 我们刚刚初始化了元素 `..1`。
                        parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
                    }
                }
            } else {
                Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
            }
        }
    }
}