форматирование длинных чисел в виде строк в python

Каков простой способ в Python форматировать целые числа в строки, представляющие тысячи с K и миллионы с M, и оставляя только пару цифр после запятой?

Я хотел бы показать 7436313 как 7,44M, а 2345 как 2,34K.

Есть ли для этого какой-либо оператор форматирования строки%? Или это можно сделать, только фактически разделив на 1000 в цикле и шаг за шагом создавая результирующую строку?


person user63503    schedule 23.02.2009    source источник


Ответы (11)


Я не думаю, что есть встроенная функция, которая делает это. Вам придется свернуть свой собственный, например:

def human_format(num):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    # add more suffixes if you need them
    return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])

print('the answer is %s' % human_format(7436313))  # prints 'the answer is 7.44M'
person Adam Rosenfield    schedule 23.02.2009
comment
999999 отображает 1000.00K вместо 1M. - person rtaft; 21.08.2017
comment
Вы можете написать long_nr=1_000_000 вместо 1000000 в редакторе, python не будет учитывать _.. - person Timo; 20.09.2020

Эта версия не страдает от ошибки в предыдущих ответах, где 999 999 дает вам 1000,0 КБ. Он также позволяет использовать только 3 значащие цифры и исключает нули в конце.

def human_format(num):
    num = float('{:.3g}'.format(num))
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])

Вывод выглядит так:

>>> human_format(999999)
'1M'
>>> human_format(999499)
'999K'
>>> human_format(9994)
'9.99K'
>>> human_format(9900)
'9.9K'
>>> human_format(6543165413)
'6.54B'
person rtaft    schedule 23.08.2017
comment
это единственная версия, которая отлично работает для меня (без раздражающих нулей в конце) - person Harry Palmer; 04.01.2018
comment
Что, если мне нужен формат '9_9K' вместо '9.9K'? - person AleB; 12.12.2019
comment
@AleB впоследствии использует функцию замены, чтобы заменить файл . с участием _ - person rtaft; 12.12.2019

Более "математическое" решение - использовать math.log:

from math import log, floor


def human_format(number):
    units = ['', 'K', 'M', 'G', 'T', 'P']
    k = 1000.0
    magnitude = int(floor(log(number, k)))
    return '%.2f%s' % (number / k**magnitude, units[magnitude])

Тесты:

>>> human_format(123456)
'123.46K'
>>> human_format(123456789)
'123.46M'
>>> human_format(1234567890)
'1.23G'
person manugrandio    schedule 03.08.2017
comment
999999 отображает 1000.00K вместо 1M. - person rtaft; 21.08.2017
comment
На мой взгляд, лучший подход, потому что он не требует цикла - person Addison Klinke; 29.01.2020

Мне нужна была эта функция сегодня, немного обновил принятый ответ для людей с Python >= 3.6:

def human_format(num, precision=2, suffixes=['', 'K', 'M', 'G', 'T', 'P']):
    m = sum([abs(num/1000.0**x) >= 1 for x in range(1, len(suffixes))])
    return f'{num/1000.0**m:.{precision}f}{suffixes[m]}'

print('the answer is %s' % human_format(7454538))  # prints 'the answer is 7.45M'

Изменить: учитывая комментарии, вы можете изменить на round(num/1000.0)

person Roelant    schedule 24.04.2017
comment
999999 отображает 1000.00K вместо 1M. - person rtaft; 21.08.2017
comment
более элегантно: m = int(math.log10(num) // 3) - person Nimrod Morag; 15.10.2019

Переменная точность и отсутствие ошибки 999999:

def human_format(num, round_to=2):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num = round(num / 1000.0, round_to)
    return '{:.{}f}{}'.format(num, round_to, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
person michauwilliam    schedule 21.04.2018
comment
В строке формата в последней строке, я думаю, вы можете заменить round(num, round_to) только на num, так как оно уже округлено до этой точки. - person tdy; 16.04.2021

Меня немного смутили некоторые вещи, которые показали другие люди, поэтому я сделал код ниже. Он округляется до второго десятичного знака, например. «23,56 миллиарда», но вы можете изменить десятичный разряд, до которого оно округляется, заменив два «100,0» в последней строке большим или меньшим числом, например. '10.0' округляется до одного десятичного знака, а '1000.0' округляется до трех десятичных знаков. Кроме того, используя этот код, он всегда округляется в меньшую сторону от того, что есть на самом деле. Вы можете изменить это, если хотите, заменив «пол» на «потолок» или «круглый».

#make the dictionary to store what to put after the result (ex. 'Billion'). You can go further with this then I did, or to wherever you wish. 
#import the desired rounding mechanism. You will not need to do this for round. 
from math import floor
magnitudeDict={0:'', 1:'Thousand', 2:'Million', 3:'Billion', 4:'Trillion', 5:'Quadrillion', 6:'Quintillion', 7:'Sextillion', 8:'Septillion', 9:'Octillion', 10:'Nonillion', 11:'Decillion'}
def simplify(num):
    num=floor(num)
    magnitude=0
    while num>=1000.0:
        magnitude+=1
        num=num/1000.0
    return(f'{floor(num*100.0)/100.0} {magnitudeDict[magnitude]}')

«f» перед строкой в ​​последней строке означает, что python знает, что вы его форматируете. Результат запуска print(simplify(34867123012.13)) таков:

34.86 Billion

Пожалуйста, дайте мне знать, если у вас есть вопросы! Спасибо, Ангус

person Angus The Car    schedule 05.12.2020
comment
Как есть, 999999 отображает 999.99 Thousand вместо 1 Million. Также это можно использовать только на Python 3.6+. - person rtaft; 02.06.2021
comment
Я знаю. Это было сделано таким образом. Для тех игр, для которых я использовал это, я хотел, чтобы у вас всегда было то, что он сказал, а не меньше, чтобы избежать путаницы, когда вы хотите купить что-то, что говорит то же самое, что говорят ваши средства, но вы не можете, потому что фактическое число на единицу меньше. Вы можете исправить это, заменив floor() на round(). - person Angus The Car; 09.06.2021

У меня была такая же потребность. И если кто-то заходит по этой теме, я нашел библиотеку для этого: https://github.com/azaitsev/millify

Надеюсь, поможет :)

person Jordi Riera    schedule 14.01.2020
comment
Millify также отображает 999999 как 1000k - person rtaft; 05.03.2020

Нет оператора форматирования строк, согласно документации. Я никогда не слышал о такой вещи, так что вам, возможно, придется свернуть свой собственный, как вы предлагаете.

person Blair Conrad    schedule 23.02.2009

Я не думаю, что для этого есть операторы формата, но вы можете просто делить на 1000, пока результат не будет между 1 и 999, а затем использовать строку формата для двух цифр после запятой. Unit — это один символ (или, возможно, небольшая строка) в большинстве случаев, который вы можете сохранить в строке или массиве и перебирать его после каждого деления.

person schnaader    schedule 23.02.2009

Я не знаю о каких-либо встроенных возможностях, подобных этой, но вот несколько потоков списка, которые могут помочь:

http://coding.derkeiler.com/Archive/Python/comp.lang.python/2005-09/msg03327.html http://mail.python.org/pipermail/python-list/2008-August/503417.html

person zweiterlinde    schedule 23.02.2009

Библиотека Numerize хороша.

from numerize import numerize
a = numerize.numerize(1000)
print(a)
1k

Спасибо @tdy за указание на это,

a = numerize.numerize(999999) 
print(a)  # 1000K 
1000K
person John Prawyn    schedule 20.07.2021
comment
имеет ту же ошибку 999999 → 1000K, что и большинство других ответов/библиотек - person tdy; 21.07.2021
comment
да. Спасибо @tdy за то, что обратили на это внимание. - person John Prawyn; 21.07.2021