💾 Archived View for gmi.karl.berlin › formatting-numbers.gmi captured on 2022-04-29 at 11:21:33. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-11-30)

-=-=-=-=-=-=-

Formatting Numbers of Unknown Order of Magnitude

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]!

3: mailto:karl@karl.berlin

Written on 2021-05-01.