diff --git a/src/uu/seq/src/numberparse.rs b/src/uu/seq/src/numberparse.rs index da235790d..06f553478 100644 --- a/src/uu/seq/src/numberparse.rs +++ b/src/uu/seq/src/numberparse.rs @@ -172,7 +172,14 @@ fn parse_exponent_no_decimal(s: &str, j: usize) -> Result Result { let x: BigDecimal = s.parse().map_err(|_| ParseNumberError::Float)?; - let num_integral_digits = i; + + // The number of integral digits is the number of chars until the period. + // + // This includes the negative sign if there is one. Also, it is + // possible that a number is expressed as "-.123" instead of + // "-0.123", but when we display the number we want it to include + // the leading 0. + let num_integral_digits = if s.starts_with("-.") { i + 1 } else { i }; let num_fractional_digits = s.len() - (i + 1); if is_minus_zero_float(s, &x) { Ok(PreciseNumber::new( @@ -215,20 +222,26 @@ fn parse_decimal_and_exponent( let num_integral_digits = { let minimum: usize = { let integral_part: f64 = s[..j].parse().map_err(|_| ParseNumberError::Float)?; - if integral_part == -0.0 && integral_part.is_sign_negative() { + if integral_part.is_sign_negative() { 2 } else { 1 } }; - - let total = i as i64 + exponent; + // Special case: if the string is "-.1e2", we need to treat it + // as if it were "-0.1e2". + let total = if s.starts_with("-.") { + i as i64 + exponent + 1 + } else { + i as i64 + exponent + }; if total < minimum as i64 { minimum } else { total.try_into().unwrap() } }; + let num_fractional_digits = if num_digits_between_decimal_point_and_e < exponent { 0 } else { @@ -532,6 +545,8 @@ mod tests { assert_eq!(num_integral_digits("123"), 3); // decimal, no exponent assert_eq!(num_integral_digits("123.45"), 3); + assert_eq!(num_integral_digits("-0.1"), 2); + assert_eq!(num_integral_digits("-.1"), 2); // exponent, no decimal assert_eq!(num_integral_digits("123e4"), 3 + 4); assert_eq!(num_integral_digits("123e-4"), 1); @@ -540,6 +555,12 @@ mod tests { assert_eq!(num_integral_digits("123.45e6"), 3 + 6); assert_eq!(num_integral_digits("123.45e-6"), 1); assert_eq!(num_integral_digits("123.45e-1"), 2); + assert_eq!(num_integral_digits("-0.1e0"), 2); + assert_eq!(num_integral_digits("-0.1e2"), 4); + assert_eq!(num_integral_digits("-.1e0"), 2); + assert_eq!(num_integral_digits("-.1e2"), 4); + assert_eq!(num_integral_digits("-1.e-3"), 2); + assert_eq!(num_integral_digits("-1.0e-4"), 2); // minus zero int assert_eq!(num_integral_digits("-0e0"), 2); assert_eq!(num_integral_digits("-0e-0"), 2); @@ -565,6 +586,8 @@ mod tests { assert_eq!(num_fractional_digits("0xff"), 0); // decimal, no exponent assert_eq!(num_fractional_digits("123.45"), 2); + assert_eq!(num_fractional_digits("-0.1"), 1); + assert_eq!(num_fractional_digits("-.1"), 1); // exponent, no decimal assert_eq!(num_fractional_digits("123e4"), 0); assert_eq!(num_fractional_digits("123e-4"), 4); @@ -575,6 +598,12 @@ mod tests { assert_eq!(num_fractional_digits("123.45e1"), 1); assert_eq!(num_fractional_digits("123.45e-6"), 8); assert_eq!(num_fractional_digits("123.45e-1"), 3); + assert_eq!(num_fractional_digits("-0.1e0"), 1); + assert_eq!(num_fractional_digits("-0.1e2"), 0); + assert_eq!(num_fractional_digits("-.1e0"), 1); + assert_eq!(num_fractional_digits("-.1e2"), 0); + assert_eq!(num_fractional_digits("-1.e-3"), 3); + assert_eq!(num_fractional_digits("-1.0e-4"), 5); // minus zero int assert_eq!(num_fractional_digits("-0e0"), 0); assert_eq!(num_fractional_digits("-0e-0"), 0); diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 490fcf60c..e58ac3a2a 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -473,6 +473,15 @@ fn test_width_decimal_scientific_notation_trailing_zeros_increment() { .no_stderr(); } +#[test] +fn test_width_negative_decimal_notation() { + new_ucmd!() + .args(&["-w", "-.1", ".1", ".11"]) + .succeeds() + .stdout_is("-0.1\n00.0\n00.1\n") + .no_stderr(); +} + #[test] fn test_width_negative_scientific_notation() { new_ucmd!() @@ -480,6 +489,54 @@ fn test_width_negative_scientific_notation() { .succeeds() .stdout_is("-0.001\n00.999\n") .no_stderr(); + new_ucmd!() + .args(&["-w", "-1.e-3", "1"]) + .succeeds() + .stdout_is("-0.001\n00.999\n") + .no_stderr(); + new_ucmd!() + .args(&["-w", "-1.0e-4", "1"]) + .succeeds() + .stdout_is("-0.00010\n00.99990\n") + .no_stderr(); + new_ucmd!() + .args(&["-w", "-.1e2", "10", "100"]) + .succeeds() + .stdout_is( + "-010 +0000 +0010 +0020 +0030 +0040 +0050 +0060 +0070 +0080 +0090 +0100 +", + ) + .no_stderr(); + new_ucmd!() + .args(&["-w", "-0.1e2", "10", "100"]) + .succeeds() + .stdout_is( + "-010 +0000 +0010 +0020 +0030 +0040 +0050 +0060 +0070 +0080 +0090 +0100 +", + ) + .no_stderr(); } /// Test that trailing zeros in the end argument do not contribute to width.