Skip to content

Commit

Permalink
Auto merge of #116301 - mj10021:issue-115737-fix, r=cuviper
Browse files Browse the repository at this point in the history
fix rounding issue with exponents in fmt

fixes issue #115737 , where the decimal places are rounded incorrectly when formatting scientific notation
  • Loading branch information
bors committed Nov 14, 2023
2 parents ba7c7a3 3f0908f commit b917524
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
11 changes: 8 additions & 3 deletions library/core/src/fmt/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 309,6 @@ macro_rules! impl_Exp {
n /= 10;
exponent = 1;
}

let (added_precision, subtracted_precision) = match f.precision() {
Some(fmt_prec) => {
// number of decimal digits minus 1
Expand All @@ -331,9 330,15 @@ macro_rules! impl_Exp {
let rem = n % 10;
n /= 10;
exponent = 1;
// round up last digit
if rem >= 5 {
// round up last digit, round to even on a tie
if rem > 5 || (rem == 5 && (n % 2 != 0 || subtracted_precision > 1 )) {
n = 1;
// if the digit is rounded to the next power
// instead adjust the exponent
if n.ilog10() > (n - 1).ilog10() {
n /= 10;
exponent = 1;
}
}
}
(n, exponent, exponent, added_precision)
Expand Down
20 changes: 16 additions & 4 deletions library/core/tests/fmt/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,28 128,40 @@ fn test_format_int_exp_precision() {
let big_int: u32 = 314_159_265;
assert_eq!(format!("{big_int:.1e}"), format!("{:.1e}", f64::from(big_int)));

//test adding precision
// test adding precision
assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2");
assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4");
assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9");
assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18");
assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38");

//test rounding
// test rounding
assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2");
assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4");
assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9");
assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18");
assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38");

//test huge precision
// test huge precision
assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000)));
//test zero precision
assert_eq!(format!("{:.0e}", 1), format!("1e0",));
assert_eq!(format!("{:.0e}", 35), format!("4e1",));

//test padding with precision (and sign)
// test padding with precision (and sign)
assert_eq!(format!("{: 10.3e}", 1), " 1.000e0");

// test precision remains correct when rounding to next power

for i in i16::MIN..=i16::MAX {
for p in 0..=5 {
assert_eq!(
format!("{i:.p$e}"),
format!("{:.p$e}", f32::from(i)),
"integer {i} at precision {p}"
);
}
}
}

#[test]
Expand Down

0 comments on commit b917524

Please sign in to comment.