python human readable large numbers
As I understand it, you only want the 'most significant' part. To do so, use floor(log10(abs(n)))
to get number of digits and then go from there. Something like this, maybe:
import math
millnames = ['',' Thousand',' Million',' Billion',' Trillion']
def millify(n):
n = float(n)
millidx = max(0,min(len(millnames)-1,
int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))
return '{:.0f}{}'.format(n / 10**(3 * millidx), millnames[millidx])
Running the above function for a bunch of different numbers:
for n in (1.23456789 * 10**r for r in range(-2, 19, 1)):
print('%20.1f: %20s' % (n,millify(n)))
0.0: 0
0.1: 0
1.2: 1
12.3: 12
123.5: 123
1234.6: 1 Thousand
12345.7: 12 Thousand
123456.8: 123 Thousand
1234567.9: 1 Million
12345678.9: 12 Million
123456789.0: 123 Million
1234567890.0: 1 Billion
12345678900.0: 12 Billion
123456789000.0: 123 Billion
1234567890000.0: 1 Trillion
12345678900000.0: 12 Trillion
123456789000000.0: 123 Trillion
1234567890000000.0: 1235 Trillion
12345678899999998.0: 12346 Trillion
123456788999999984.0: 123457 Trillion
1234567890000000000.0: 1234568 Trillion
With Python2.7+ or v3 you just use the "," option in your string formatting - see PEP 378: Format Specifier for Thousands Separator for more info:
>>> "{:,}".format(100000000)
'100,000,000'
With Python3.6+ you can also use the "_" format - see PEP 515 for details:
>>> "{:_}".format(100000000)
'100_000_000'
or you can use a similar syntax with f-strings:
>>> number = 100000000
>>>f"{number:,}"
'100,000,000'
So I don't have to squint while reading big numbers, I have the 2.7 version of the code wrapped up in a shell function:
human_readable_numbers () {
python2.7 -c "print('{:,}').format($1)"
}
Lastly, if for some reason you must work with code from Python versions 2.6 or earlier, you can solve the problem using the locale
standard library module:
import locale
locale.setlocale(locale.LC_ALL, 'en_US')
locale.format('%d', 2**32, grouping=True) # returns '4,294,967,296'
From here:
def commify(n):
if n is None: return None
if type(n) is StringType:
sepdec = localenv['mon_decimal_point']
else:
#if n is python float number we use everytime the dot
sepdec = '.'
n = str(n)
if sepdec in n:
dollars, cents = n.split(sepdec)
else:
dollars, cents = n, None
r = []
for i, c in enumerate(reversed(str(dollars))):
if i and (not (i % 3)):
r.insert(0, localenv['mon_thousands_sep'])
r.insert(0, c)
out = ''.join(r)
if cents:
out += localenv['mon_decimal_point'] + cents
return out
That number seems pretty human-readable to me. An unfriendly number would be 187289840422780.00. To add commas, you could create your own function or search for one (I found this):
import re
def comma_me(amount):
orig = amount
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', amount)
if orig == new:
return new
else:
return comma_me(new)
f = 12345678
print comma_me(`f`)
Output: 12,345,678
If you want to round a number to make it more readable, there is a python function for that: round()
.
You could move even further away from the actual data and say "A very high amount" or "Above 100 trillion" using a function that would return a different value based on your programmed benchmarks.