From ece6bebb5cd87b0bc0121dbfc35c318d6d069e22 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 3 Mar 2025 15:18:00 +0100 Subject: [PATCH 1/4] uucore: format: Fix capitalization of 0 in scientific formating 0.0E+00 was not capitalized properly when using `%E` format. Fixes #7382. Test: cargo test --package uucore --all-features float Test: cargo run printf "%E\n" 0 => 0.000000E+00 --- .../src/lib/features/format/num_format.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index 0acec0598a1..6caf1bfceec 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -350,11 +350,16 @@ fn format_float_scientific( case: Case, force_decimal: ForceDecimal, ) -> String { + let exp_char = match case { + Case::Lowercase => 'e', + Case::Uppercase => 'E', + }; + if f == 0.0 { return if force_decimal == ForceDecimal::Yes && precision == 0 { - "0.e+00".into() + format!("0.{exp_char}+00") } else { - format!("{:.*}e+00", precision, 0.0) + format!("{:.*}{exp_char}+00", precision, 0.0) }; } @@ -375,11 +380,6 @@ fn format_float_scientific( "" }; - let exp_char = match case { - Case::Lowercase => 'e', - Case::Uppercase => 'E', - }; - format!("{normalized:.precision$}{additional_dot}{exp_char}{exponent:+03}") } @@ -582,6 +582,10 @@ mod test { assert_eq!(f(12.345_678_9), "1.234568e+01"); assert_eq!(f(1_000_000.0), "1.000000e+06"); assert_eq!(f(99_999_999.0), "1.000000e+08"); + + let f = |x| format_float_scientific(x, 6, Case::Uppercase, ForceDecimal::No); + assert_eq!(f(0.0), "0.000000E+00"); + assert_eq!(f(123_456.789), "1.234568E+05"); } #[test] From 3cbc22828d01e3bf71dd10fee26c1bc29d9b73cd Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 3 Mar 2025 14:42:52 +0100 Subject: [PATCH 2/4] uucore: format: Fix default Float precision in try_from_spec The default precision is 6, no matter the format. This applies to all float formats, not just "%g" (aka FloatVariant::Shortest). Fixes #7361. --- src/uucore/src/lib/features/format/num_format.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index 6caf1bfceec..fac733a2253 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -293,13 +293,7 @@ impl Formatter for Float { let precision = match precision { Some(CanAsterisk::Fixed(x)) => x, - None => { - if matches!(variant, FloatVariant::Shortest) { - 6 - } else { - 0 - } - } + None => 6, // Default float precision (C standard) Some(CanAsterisk::Asterisk) => return Err(FormatError::WrongSpecType), }; From bd5ff889f9085b1ecb3a28516ed643ee104594c7 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 3 Mar 2025 15:07:38 +0100 Subject: [PATCH 3/4] seq: Add tests for default float formats Add tests for some of the default float formats (%f, %g, %E), mostly to check that the default precision is correctly set to 6 digits. --- tests/by-util/test_seq.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 0c708506f7e..716b5cb88f4 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -708,6 +708,30 @@ fn test_format_option() { .stdout_only("0.00\n0.10\n0.20\n0.30\n0.40\n0.50\n"); } +#[test] +fn test_format_option_default_precision() { + new_ucmd!() + .args(&["-f", "%f", "0", "0.7", "2"]) + .succeeds() + .stdout_only("0.000000\n0.700000\n1.400000\n"); +} + +#[test] +fn test_format_option_default_precision_short() { + new_ucmd!() + .args(&["-f", "%g", "0", "0.987654321", "2"]) + .succeeds() + .stdout_only("0\n0.987654\n1.97531\n"); +} + +#[test] +fn test_format_option_default_precision_scientific() { + new_ucmd!() + .args(&["-f", "%E", "0", "0.7", "2"]) + .succeeds() + .stdout_only("0.000000E+00\n7.000000E-01\n1.400000E+00\n"); +} + #[test] #[ignore = "Need issue #2660 to be fixed"] fn test_auto_precision() { From 8e1e850c280ac89fbf9a8d9600fe296ca422dd86 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 3 Mar 2025 15:08:28 +0100 Subject: [PATCH 4/4] seq: Enable test_auto_precision and test_undefined Those tests appear to have been fixed, enable them. --- tests/by-util/test_seq.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 716b5cb88f4..1fae070f41e 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -733,7 +733,6 @@ fn test_format_option_default_precision_scientific() { } #[test] -#[ignore = "Need issue #2660 to be fixed"] fn test_auto_precision() { new_ucmd!() .args(&["1", "0x1p-1", "2"]) @@ -742,7 +741,6 @@ fn test_auto_precision() { } #[test] -#[ignore = "Need issue #3318 to be fixed"] fn test_undefined() { new_ucmd!() .args(&["1e-9223372036854775808"])