Summary
compute_num_digits in src/uu/seq/src/numberparse.rs counts integral digits of an operand, then adds a positive decimal exponent to that count. When the mantissa has a leading 0 (the .X / -0.X special case), shifting the decimal point past that zero annihilates it, but the code still keeps the counted digit and adds the exponent on top. The inflated integral-digit count makes seq -w pad output one character wider than the widest rendered value.
Static-analysis finding based on reading main; not executed here.
Location
- File:
src/uu/seq/src/numberparse.rs
- Function:
compute_num_digits
- Relevant code:
let (mut int_digits, mut frac_digits) = match parts[0].find('.') {
Some(i) => {
// Cover special case .X and -.X where we behave as if there was a leading 0:
// 0.X, -0.X.
let int_digits = match i {
0 => 1,
1 if parts[0].starts_with('-') => 2,
_ => i,
};
(int_digits, parts[0].len() - i - 1)
}
None => (parts[0].len(), 0),
};
...
if exp > 0 {
int_digits += exp.try_into().unwrap_or(0);
}
Problem
For the operand "0.5e1" (value 5):
find('.') -> i = 1; the special case yields int_digits = 1 (the counted leading 0) and frac_digits = 1.
exp = 1 > 0 -> int_digits += 1 -> 2.
- But
0.5e1 == 5, whose rendered form "5" has exactly 1 integral digit: shifting the point past the leading zero removes that zero (05e1 would be 5, not 05). The correct count is therefore max(1, i + exp - 1)-style logic that first cancels the pad digit; instead both are summed.
- Downstream,
seq -w 0.5e1 0.5e1 derives padding = max(integral digits) = 2 and prints 05.
The file's own tests encode the same over-count (e.g. -0.1e2 expected to contribute width 4, while -10 renders as 3 characters).
Trigger / Reproduction
Based on source reading:
$ seq -w 0.5e1 0.5e1
05 # actual
5 # expected
Same class: .5e2, -0.1e2, any operand whose mantissa starts with 0/. and whose exponent is at least the number of fractional digits.
Expected Behavior
The equal-width padding should equal the width of the widest actually-rendered value among all sequence elements - here 5, so no padding.
Actual Behavior
Padding is computed from an inflated digit count that double-counts the special-cased leading zero once the exponent moves past it, producing spurious leading zeros / overwide fields.
Impact
Wrong textual output for documented input syntax (scientific notation is accepted by seq's parser). Cosmetic rather than data-destructive, but deterministic and visible in scripts relying on fixed-width columns.
Suggested Direction
When i corresponds to the leading-zero special case, subtract the consumed pad digit from int_digits before applying a positive exponent (or compute the integer-part width from the normalized value mantissa * 10^exp directly).
Evidence
- Lines 60-66 explicitly count the synthesized leading zero as an integral digit.
- Lines 77-78 add the exponent unconditionally for
exp > 0; there is no interaction between the two adjustments anywhere in the function.
Summary
compute_num_digitsinsrc/uu/seq/src/numberparse.rscounts integral digits of an operand, then adds a positive decimal exponent to that count. When the mantissa has a leading0(the.X/-0.Xspecial case), shifting the decimal point past that zero annihilates it, but the code still keeps the counted digit and adds the exponent on top. The inflated integral-digit count makesseq -wpad output one character wider than the widest rendered value.Static-analysis finding based on reading
main; not executed here.Location
src/uu/seq/src/numberparse.rscompute_num_digitsProblem
For the operand
"0.5e1"(value5):find('.')->i = 1; the special case yieldsint_digits = 1(the counted leading0) andfrac_digits = 1.exp = 1 > 0->int_digits += 1-> 2.0.5e1 == 5, whose rendered form"5"has exactly 1 integral digit: shifting the point past the leading zero removes that zero (05e1would be5, not05). The correct count is thereforemax(1, i + exp - 1)-style logic that first cancels the pad digit; instead both are summed.seq -w 0.5e1 0.5e1derivespadding = max(integral digits) = 2and prints05.The file's own tests encode the same over-count (e.g.
-0.1e2expected to contribute width 4, while-10renders as 3 characters).Trigger / Reproduction
Based on source reading:
Same class:
.5e2,-0.1e2, any operand whose mantissa starts with0/.and whose exponent is at least the number of fractional digits.Expected Behavior
The equal-width padding should equal the width of the widest actually-rendered value among all sequence elements - here
5, so no padding.Actual Behavior
Padding is computed from an inflated digit count that double-counts the special-cased leading zero once the exponent moves past it, producing spurious leading zeros / overwide fields.
Impact
Wrong textual output for documented input syntax (scientific notation is accepted by seq's parser). Cosmetic rather than data-destructive, but deterministic and visible in scripts relying on fixed-width columns.
Suggested Direction
When
icorresponds to the leading-zero special case, subtract the consumed pad digit fromint_digitsbefore applying a positive exponent (or compute the integer-part width from the normalized valuemantissa * 10^expdirectly).Evidence
exp > 0; there is no interaction between the two adjustments anywhere in the function.