seq -w: positive exponents in scientific-notation operands produce wrong padding width (leading zero not cancelled)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 24.1k
- Forks
- 2k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 365
Description
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 yieldsint_digits = 1(the counted leading0) andfrac_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 (05e1would be5, not05). The correct count is thereforemax(1, i + exp - 1)-style logic that first cancels the pad digit; instead both are summed. - Downstream,
seq -w 0.5e1 0.5e1derivespadding = max(integral digits) = 2and prints05.
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/uu/seq/src/numberparse.rs at compute_num_digits and inspect the existing tests for scientific-notation operands. Run the seq tests and reproduce seq -w 0.5e1 0.5e1, then verify that leading-zero cases such as .5e2 and -0.1e2 no longer produce wider-than-needed output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100