Skip to content

Commit f5e8609

Browse files
committed
uucore: num_format: Move common scientific formatting code to a function
Both format_float_scientific and format_float_shortest carry the same code, moving it to a single function will make it possible to optimize both.
1 parent 1c6be20 commit f5e8609

File tree

1 file changed

+23
-25
lines changed

1 file changed

+23
-25
lines changed

src/uucore/src/lib/features/format/num_format.rs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,27 @@ fn format_float_decimal(
374374
format!("{bd:.precision$}")
375375
}
376376

377+
/// Converts a `&BigDecimal` to a scientific-like `X.XX * 10^e`.
378+
/// - The returned `String` contains the digits `XXX`, _without_ the separating
379+
/// `.` (the caller must add that to get a valid scientific format number).
380+
/// - `e` is an integer exponent.
381+
fn bd_to_string_exp_with_prec(bd: &BigDecimal, precision: u64) -> (String, i64) {
382+
// Round bd to precision digits (including the leading digit)
383+
// We call `with_prec` twice as it will produce an extra digit if rounding overflows
384+
// (e.g. 9995.with_prec(3) => 1000 * 10^1, but we want 100 * 10^2).
385+
let bd_round = bd.with_prec(precision).with_prec(precision);
386+
387+
// Convert to the form XXX * 10^-p (XXX is precision digit long)
388+
let (frac, p) = bd_round.as_bigint_and_exponent();
389+
390+
let digits = frac.to_str_radix(10);
391+
// If we end up with scientific formatting, we would convert XXX to X.XX:
392+
// that divides by 10^(precision-1), so add that to the exponent.
393+
let exponent = -p + precision as i64 - 1;
394+
395+
(digits, exponent)
396+
}
397+
377398
fn format_float_scientific(
378399
bd: &BigDecimal,
379400
precision: Option<usize>,
@@ -395,20 +416,8 @@ fn format_float_scientific(
395416
};
396417
}
397418

398-
// Round bd to (1 + precision) digits (including the leading digit)
399-
// We call `with_prec` twice as it will produce an extra digit if rounding overflows
400-
// (e.g. 9995.with_prec(3) => 1000 * 10^1, but we want 100 * 10^2).
401-
let bd_round = bd
402-
.with_prec(precision as u64 + 1)
403-
.with_prec(precision as u64 + 1);
404-
405-
// Convert to the form XXX * 10^-e (XXX is 1+precision digit long)
406-
let (frac, e) = bd_round.as_bigint_and_exponent();
407-
408-
// Scale down "XXX" to "X.XX": that divides by 10^precision, so add that to the exponent.
409-
let digits = frac.to_str_radix(10);
419+
let (digits, exponent) = bd_to_string_exp_with_prec(bd, precision as u64 + 1);
410420
let (first_digit, remaining_digits) = digits.split_at(1);
411-
let exponent = -e + precision as i64;
412421

413422
let dot =
414423
if !remaining_digits.is_empty() || (precision == 0 && ForceDecimal::Yes == force_decimal) {
@@ -445,18 +454,7 @@ fn format_float_shortest(
445454
};
446455
}
447456

448-
// Round bd to precision digits (including the leading digit)
449-
// We call `with_prec` twice as it will produce an extra digit if rounding overflows
450-
// (e.g. 9995.with_prec(3) => 1000 * 10^1, but we want 100 * 10^2).
451-
let bd_round = bd.with_prec(precision as u64).with_prec(precision as u64);
452-
453-
// Convert to the form XXX * 10^-p (XXX is precision digit long)
454-
let (frac, e) = bd_round.as_bigint_and_exponent();
455-
456-
let digits = frac.to_str_radix(10);
457-
// If we end up with scientific formatting, we would convert XXX to X.XX:
458-
// that divides by 10^(precision-1), so add that to the exponent.
459-
let exponent = -e + precision as i64 - 1;
457+
let (digits, exponent) = bd_to_string_exp_with_prec(bd, precision as u64);
460458

461459
if exponent < -4 || exponent >= precision as i64 {
462460
// Scientific-ish notation (with a few differences)

0 commit comments

Comments
 (0)