I was thinking of writing a PEP to support formatting floats with SI (decimal) and IEC (binary) prefixes natively for float
(and maybe other types if makes sense) but wanted to feel it out first.
I’ve implemented what I want to propose in the Prefixed package as a subclass of float
. It came out of some work I was doing a few years ago and has been refined since then through use and feedback.
The format specification changes are outlined here, but in summary it adds:
- New presentation types
-
'h'
: SI format. Outputs the number with closest divisible SI prefix. (k, M, G, …) -
'H'
: Same as'h'
but treats precision as significant digits -
'k'
: IEC Format. Outputs the number with closest divisible IEC prefix. (Ki, Mi, Gi, …) -
'K'
: Same as'k'
but treats precision as significant digits -
'm'
: Short IEC Format. Same as'k'
but only a single character. (K, M, G, …) -
'M'
: Same as'm'
but treats precision as significant digits
-
- New flags
-
'!'
: Add a single space between number and prefix -
'!!'
: Same as'!'
but drop space if there is no prefix
-
- New field
- Margin, denoted with
'%'
, raises or lowers the threshold for prefixes
- Margin, denoted with
Some examples of what this would look like if implemented directly into the float
type. You can do these today with preflixed.Float
.
Simple SI (decimal) case
>>> f'{3250.0:.2h}'
'3.25k'
Same thing with the '!'
flag to add a space
>>> f'{3250.0:!.2h}'
'3.25 k'
Simple IEC (binary) case
>>> f'{2048.0:.2k}B'
'2.00KiB'
Same thing, but short form
>>> f'{2048.0:.2m}B'
'2.00KB'
Difference in the way precision is handled when treated like significant digits
>>> f'{1246.0:.3h}'
'1.246k'
>>> f'{1246.0:.3H}'
'1.25k'
Difference in the way prefixes are determined based on margin field. The example lowers the threshold by 5%.
>>> f'{950.0:.2h}'
'950.00'
>>> f'{950.0:%-5.2h}'
'0.95k'
I couldn’t find a previous discussion of something similar on this forum, but there was some discussion in a cpython issue 75930.
When I originally looked at this problem, there seemed to be a lot of packages and code samples solving specific uses, but not really any generic solutions. This is my attempt to imagine what it would look like if this was generic and native. I think it’s a common problem and would get a lot of use.
I would appreciate your thoughts and suggestions. Please check out Prefixed if you want to test drive the proposal. And if you’d like to help with writing the PEP or the C code, please reach out.
(Sorry for the lack of links, apparently new users can only have 2 in a post)