1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 11:07:44 +00:00

Merge pull request #2741 from jfinkels/seq-width-negative-decimal

seq: correct width for certain negative decimals
This commit is contained in:
Sylvestre Ledru 2021-12-24 20:46:43 +01:00 committed by GitHub
commit 4ada922a4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 4 deletions

View file

@ -172,7 +172,14 @@ fn parse_exponent_no_decimal(s: &str, j: usize) -> Result<PreciseNumber, ParseNu
/// ``` /// ```
fn parse_decimal_no_exponent(s: &str, i: usize) -> Result<PreciseNumber, ParseNumberError> { fn parse_decimal_no_exponent(s: &str, i: usize) -> Result<PreciseNumber, ParseNumberError> {
let x: BigDecimal = s.parse().map_err(|_| ParseNumberError::Float)?; 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); let num_fractional_digits = s.len() - (i + 1);
if is_minus_zero_float(s, &x) { if is_minus_zero_float(s, &x) {
Ok(PreciseNumber::new( Ok(PreciseNumber::new(
@ -215,20 +222,26 @@ fn parse_decimal_and_exponent(
let num_integral_digits = { let num_integral_digits = {
let minimum: usize = { let minimum: usize = {
let integral_part: f64 = s[..j].parse().map_err(|_| ParseNumberError::Float)?; 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 2
} else { } else {
1 1
} }
}; };
// Special case: if the string is "-.1e2", we need to treat it
let total = i as i64 + exponent; // 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 { if total < minimum as i64 {
minimum minimum
} else { } else {
total.try_into().unwrap() total.try_into().unwrap()
} }
}; };
let num_fractional_digits = if num_digits_between_decimal_point_and_e < exponent { let num_fractional_digits = if num_digits_between_decimal_point_and_e < exponent {
0 0
} else { } else {
@ -532,6 +545,8 @@ mod tests {
assert_eq!(num_integral_digits("123"), 3); assert_eq!(num_integral_digits("123"), 3);
// decimal, no exponent // decimal, no exponent
assert_eq!(num_integral_digits("123.45"), 3); 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 // exponent, no decimal
assert_eq!(num_integral_digits("123e4"), 3 + 4); assert_eq!(num_integral_digits("123e4"), 3 + 4);
assert_eq!(num_integral_digits("123e-4"), 1); 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.45e6"), 3 + 6);
assert_eq!(num_integral_digits("123.45e-6"), 1); assert_eq!(num_integral_digits("123.45e-6"), 1);
assert_eq!(num_integral_digits("123.45e-1"), 2); 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 // minus zero int
assert_eq!(num_integral_digits("-0e0"), 2); assert_eq!(num_integral_digits("-0e0"), 2);
assert_eq!(num_integral_digits("-0e-0"), 2); assert_eq!(num_integral_digits("-0e-0"), 2);
@ -565,6 +586,8 @@ mod tests {
assert_eq!(num_fractional_digits("0xff"), 0); assert_eq!(num_fractional_digits("0xff"), 0);
// decimal, no exponent // decimal, no exponent
assert_eq!(num_fractional_digits("123.45"), 2); 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 // exponent, no decimal
assert_eq!(num_fractional_digits("123e4"), 0); assert_eq!(num_fractional_digits("123e4"), 0);
assert_eq!(num_fractional_digits("123e-4"), 4); 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.45e1"), 1);
assert_eq!(num_fractional_digits("123.45e-6"), 8); assert_eq!(num_fractional_digits("123.45e-6"), 8);
assert_eq!(num_fractional_digits("123.45e-1"), 3); 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 // minus zero int
assert_eq!(num_fractional_digits("-0e0"), 0); assert_eq!(num_fractional_digits("-0e0"), 0);
assert_eq!(num_fractional_digits("-0e-0"), 0); assert_eq!(num_fractional_digits("-0e-0"), 0);

View file

@ -473,6 +473,15 @@ fn test_width_decimal_scientific_notation_trailing_zeros_increment() {
.no_stderr(); .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] #[test]
fn test_width_negative_scientific_notation() { fn test_width_negative_scientific_notation() {
new_ucmd!() new_ucmd!()
@ -480,6 +489,54 @@ fn test_width_negative_scientific_notation() {
.succeeds() .succeeds()
.stdout_is("-0.001\n00.999\n") .stdout_is("-0.001\n00.999\n")
.no_stderr(); .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. /// Test that trailing zeros in the end argument do not contribute to width.