Как напечатать число с запятыми в качестве разделителей тысяч? - PullRequest
605 голосов
/ 01 декабря 2009

Я пытаюсь напечатать целое число в Python 2.6.1 с запятыми в качестве разделителей тысяч. Например, я хочу показать число 1234567 как 1,234,567. Как бы я поступил так? Я видел много примеров в Google, но я ищу самый простой практический способ.

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

Ответы [ 27 ]

1524 голосов
/ 24 мая 2012

Локаль не знает

'{:,}'.format(value)  # For Python ≥2.7
f'{value:,}'  # For Python ≥3.7

Знание локали

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')  # Customize

'{:n}'.format(value)  # For Python ≥2.7
f'{value:n}'  # For Python ≥3.7

Ссылки

Per Спецификация формата Mini-Language ,

Опция ',' сигнализирует об использовании запятой для разделителя тысяч. Для разделителя, поддерживающего локали, используйте вместо этого целочисленный тип представления 'n'.

274 голосов
/ 01 декабря 2009

Я получил это на работу:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format("%d", 1255000, grouping=True)
'1,255,000'

Конечно, вам не нужна поддержка интернационализации, но она ясна, лаконична и использует встроенную библиотеку.

P.S. Этот% d является обычным форматером в стиле%. У вас может быть только один форматер, но он может быть любым, что вам нужно с точки зрения ширины поля и настроек точности.

P.P.S. Если вы не можете заставить работать locale, я бы предложил модифицированную версию ответа Марка:

def intWithCommas(x):
    if type(x) not in [type(0), type(0L)]:
        raise TypeError("Parameter must be an integer.")
    if x < 0:
        return '-' + intWithCommas(-x)
    result = ''
    while x >= 1000:
        x, r = divmod(x, 1000)
        result = ",%03d%s" % (r, result)
    return "%d%s" % (x, result)

Рекурсия полезна для отрицательного случая, но одна рекурсия на запятую мне кажется немного чрезмерной.

109 голосов
/ 19 января 2012

За неэффективность и нечитаемость трудно победить:

>>> import itertools
>>> s = '-1234567'
>>> ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-')
91 голосов
/ 01 декабря 2009

Вот код группирования локали после удаления ненужных частей и его небольшой очистки:

(следующее работает только для целых чисел)

def group(number):
    s = '%d' % number
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

>>> group(-23432432434.34)
'-23,432,432,434'

Здесь уже есть несколько хороших ответов. Я просто хочу добавить это для дальнейшего использования. В Python 2.7 будет указатель формата для разделителя тысяч. Согласно Python Docs это работает так

>>> '{:20,.2f}'.format(f)
'18,446,744,073,709,551,616.00'

В python3.1 вы можете сделать то же самое, как это:

>>> format(1234567, ',d')
'1,234,567'
55 голосов
/ 28 июля 2017

Я удивлен, что никто не упомянул, что вы можете сделать это с f-строками в Python 3.6 так просто:

>>> num = 10000000
>>> print(f"{num:,d}")
10,000,000

... где часть после двоеточия является спецификатором формата. Запятая - это требуемый символ-разделитель, поэтому f"{num:_d}" использует запятую вместо запятой.

Это эквивалентно использованию format(num, ",d") для более старых версий Python 3.

36 голосов
/ 19 июля 2012

Вот замена регулярного выражения в одну строку:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)

Работает только для интегральных выходов:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Returns: '1,234,567,890'

val = 1234567890.1234567890
# Returns: '1,234,567,890'

Или для чисел с плавающей запятой менее 4 цифр измените спецификатор формата на %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Returns: '1,234,567,890.123'

NB: Не работает правильно с более чем тремя десятичными цифрами, так как будет пытаться сгруппировать десятичную часть:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Returns: '1,234,567,890.12,346'

Как это работает

Давайте разберемся:

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Find one digit...
     (?=            # that is followed by...
         (\d{3})+   # one or more groups of three digits...
         (?!\d)     # which are not followed by any more digits.
     )",

repl = \
    r"\1,",         # Replace that one digit by itself, followed by a comma,
                    # and continue looking for more matches later in the string.
                    # (re.sub() replaces all matches it finds in the input)

string = \
    "%d" % val      # Format the string as a decimal to begin with
24 голосов
/ 24 июля 2016

Это то, что я делаю для поплавков. Хотя, если честно, я не уверен, для каких версий он работает - я использую 2.7:

my_number = 4385893.382939491

my_string = '{:0,.2f}'.format(my_number)

Возвращает: 4 385 893,38

Обновление: у меня недавно была проблема с этим форматом (не могу сказать вам точную причину), но я смог ее исправить, сбросив 0:

my_string = '{:,.2f}'.format(my_number)
19 голосов
/ 17 августа 2015

Вы также можете использовать '{:n}'.format( value ) для представления локали. Я думаю, что это самый простой способ решения локали.

Для получения дополнительной информации выполните поиск thousands в Python DOC .

Для валюты вы можете использовать locale.currency, устанавливая флаг grouping:

Код

import locale

locale.setlocale( locale.LC_ALL, '' )
locale.currency( 1234567.89, grouping = True )

выход

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'
11 голосов
/ 01 декабря 2009

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

def intToStringWithCommas(x):
    if type(x) is not int and type(x) is not long:
        raise TypeError("Not an integer!")
    if x < 0:
        return '-' + intToStringWithCommas(-x)
    elif x < 1000:
        return str(x)
    else:
        return intToStringWithCommas(x / 1000) + ',' + '%03d' % (x % 1000)

Сказав, что, если кто-то найдет стандартный способ сделать это, вы должны использовать его вместо этого.

8 голосов
/ 28 сентября 2017

Слегка расширяя ответ Яна Шнайдера:

Если вы хотите использовать пользовательский разделитель тысяч, самое простое решение:

'{:,}'.format(value).replace(',', your_custom_thousands_separator)

Примеры * * 1 006 '{:,.2f}'.format(123456789.012345).replace(',', ' ') Если вы хотите, чтобы немецкое представление было таким, оно становится немного сложнее: ('{:,.2f}'.format(123456789.012345) .replace(',', ' ') # 'save' the thousands separators .replace('.', ',') # dot to comma .replace(' ', '.')) # thousand separators to dot

...