Found by the fuzz_numfmt cargo-fuzz target.
When --to=iec is combined with a --format that specifies more decimal places than GNU's internal IEC-scaled precision (3 decimals), uutils prints the full f64 value while GNU zero-pads after its rounded value.
Rust (incorrect)
$ LC_ALL=C target/debug/coreutils numfmt --to=iec --format=%-17.5f -- 310174
302.90430K
GNU (reference)
$ LC_ALL=C /usr/bin/numfmt --to=iec --format=%-17.5f -- 310174
302.90500K
More reproducers
| input |
uutils |
GNU |
| 1500 |
1.46485K |
1.46500K |
| 999999 |
976.56153K |
976.56200K |
| 310174 |
302.90430K |
302.90500K |
Root cause (hypothesis)
With --to=iec, GNU rounds the scaled value to 3 decimals (its native IEC display precision) before applying the user-requested %.Nf precision, so any extra digits come out as zeros. uutils passes the full f64 to the format, so the low-order bits of the division leak into the output.
Found by the
fuzz_numfmtcargo-fuzz target.When
--to=iecis combined with a--formatthat specifies more decimal places than GNU's internal IEC-scaled precision (3 decimals), uutils prints the full f64 value while GNU zero-pads after its rounded value.Rust (incorrect)
GNU (reference)
More reproducers
1.46485K1.46500K976.56153K976.56200K302.90430K302.90500KRoot cause (hypothesis)
With
--to=iec, GNU rounds the scaled value to 3 decimals (its native IEC display precision) before applying the user-requested%.Nfprecision, so any extra digits come out as zeros. uutils passes the full f64 to the format, so the low-order bits of the division leak into the output.