💾 Archived View for gmi.karl.berlin › formatting-numbers.gmi captured on 2022-06-11 at 20:30:23. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-11-30)
-=-=-=-=-=-=-
Sometimes, I write programs that need to display numbers where I don't know how big or small they will be. The most common approaches of printing numbers won't be very helpful in such a case.
# Default print: more decimal places than useful >>> print(1324325425.3254435363463) 1324325425.3254435 # Fixed amount of decimal places: better, but ... >>> print("{:.0f}".format(1324325425.3254435363463)) 1324325425 # ...useless results for small numbers >>> print("{:.0f}".format(0.3254435363463)) 0
A good way to deal with this problem is to use the scientific notation[1], which displays the mantissa and exponent separately.
1: https://en.wikipedia.org/wiki/Scientific_notation
>>> print("{:e}".format(1324325425.3254435363463)) 1.324325e+09 >>> print("{:e}".format(0.3254435363463)) 3.254435e-01
However, not everyone is used to reading the scientific notation and many programs don't accept it as input. What I often want to have is a format that:
One way to reach this is to round to a fixed number of significant figures[2].
2: https://en.wikipedia.org/wiki/Significant_figures
>>> def fmt_sig(x, sig_figures=3): ... show_dec = -floor(log10(abs(x)) + 1) + sig_figures ... return round(x, show_dec) ... >>> print(fmt_sig(1324325425.3254435363463)) 1320000000.0 >>> print(fmt_sig(0.3254435363463)) 0.325
But rounding the big number can be confusing because it only has an accuracy of three digits while showing eleven digits. My suggested solution is to format numbers with a *minimum* number of significant figures and to print all places before the decimal point for big numbers.
>>> def fmt_min_sig(x, min_sig_figures=3): ... show_dec = max(-floor(log10(abs(x)) + 1) + min_sig_figures, 0) ... return ("{:." + str(show_dec) + "f}").format(x) ... >>> print(fmt_min_sig(1324325425.3254435363463)) 1324325425 >>> print(fmt_min_sig(0.3254435363463)) 0.325 >>> print(fmt_min_sig(12.3254435363463)) 12.3
This approach has worked well for me, but I have not seen it any other code bases. That makes me wonder: Did I miss any downsides? Are others doing the same and I just didn't notice? Or is there a better way to do the same? If you have the answer to one of these questions, please let me know[3]!
Written on 2021-05-01.