fmtscale() handling of values in the range [1, 9] is weird and arguably broken #1366
Description
I was perplexed why the test coverage of fmtscale()
was so low since it is a small function and has an explicit unit test. So I added more test cases to src/lib/libast/tests/string/fmtscale.c. I was surprised to find that zero becomes 0
but one becomes 1.0
. Similarly 9 becomes 9.0
. But ten becomes 10
. Why do values between zero and ten have a decimal place? It is due to this block of code:
ast/src/lib/libast/string/fmtscale.c
Lines 79 to 82 in 6a08aa4
Notice that values like 11 and 999 are also converted to strings without a decimal point. Why are values in the range [1, 9] treated differently than zero or [10, 999]? This makes no sense. Values like seven are no more ambiguous than 666. Either both should have a decimal place or neither should.
In fact, the basic behavior of fmtscale()
is suspect. Why is 999 rendered as 999
when scaled by 1000 rather than 1.0k
? Or 500 as 500
rather than 0.5k
?
The only use of the fmtscale()
function is in sfvprintf()
. There doesn't appear to be an analog in the stdio code for this behavior. The only tests that invoke fmtscale()
are in src/cmd/ksh93/tests/b_printf.sh. Specifically, by tests like this one:
[[ $(printf "%#d" 1000) = "1.0k" ]] || log_error "printf %#d does not set k suffix"
Note that printf
on other platforms behaves very differently for these cases. Either reporting an error or producing more sensible output (i.e., without the unexpected decimal value).