Skip to content

Instantly share code, notes, and snippets.

@Stefan-Code
Last active July 23, 2022 17:15
Show Gist options
  • Save Stefan-Code/6cbcde79eff1e78d51e6e9a8b971e1a7 to your computer and use it in GitHub Desktop.
Save Stefan-Code/6cbcde79eff1e78d51e6e9a8b971e1a7 to your computer and use it in GitHub Desktop.
Format numbers with the appropriate SI prefix
def si_format(number, unit=''):
"""
Formats a number with the appropriate SI prefix.
Example:
>>> si_format(500000, unit='B')
'500 KB'
>>> si_format(2000000, unit='B')
'2 MB'
>>> si_format(1e-6, unit='m')
'1 μm'
"""
si_prefixes = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm']
try:
# max(min(...)) to clip list indices to the valid range.
# floor() yields *max.* 3 places before the decimal separator
# each SI prefixes increases by a factor of 1000 = 10^3
# scaling factors for numbers < 1 are achieved with Python's fancy negative indexing
scaling_index = max(min(math.floor(math.log10(abs(number)) / 3), 8), -8)
except ValueError:
# log10(0) is undefined
scaling_index = 0
# Formatting 4g = 4 *valid* digits (before or after the decimal separator)
return f'{number / (1000 ** scaling_index):.4g} {si_prefixes[scaling_index]}{unit}'.rstrip()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment