12

Как вывести число с разделением тысяч запятыми

12

Как напечатать целое число с запятыми в качестве разделителей тысяч?

У меня есть целое число, например, 1234567, и мне нужно отформатировать его так, чтобы оно отображалось с запятыми в качестве разделителей тысяч, то есть 1,234,567.

Важно, чтобы форматирование не зависело от локали и не принимало во внимание разницу между запятыми и точками.

Как я могу реализовать это в своем коде?

5 ответ(ов)

3

Я смог это сделать следующим образом:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format_string("%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("Параметр должен быть целым числом.")
    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)

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

P.P.P.S. В старых версиях Python использовался метод format вместо format_string.

1

Для неэффективности и трудночитаемости это трудно превзойти:

>>> 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('-,','-')

Этот код создает строку с разделителями, но он сложен для понимания и не самый оптимальный способ достичь результата. Основные проблемы заключаются в использовании нескольких операций реверсирования и в том, что функция izip_longest возвращает многообещающий, но сложный в понимании результат. Если вы стремитесь к более читаемому и более эффективному решению, стоит рассмотреть альтернативные подходы, такие как использование более простых списков или функций для обработки строк.

0

Вот что я делаю для форматирования чисел с плавающей точкой. Хотя, если честно, я не уверен, для каких версий это работает — я использую Python 2.7:

my_number = 4385893.382939491

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

Это вернет: 4,385,893.38

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

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

Теперь все работает корректно.

0

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

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

Этот код работает только для целочисленных значений:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Возвращает: '1,234,567,890'

val = 1234567890.1234567890
# Возвращает: '1,234,567,890'

Для работы с числами с плавающей запятой, если требуется менее 4 цифр после запятой, измените спецификатор формата на %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Возвращает: '1,234,567,890.123'

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

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Возвращает: '1,234,567,890.12,346'

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

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

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Найти одну цифру...
     (?=            # за которой следует...
         (\d{3})+   # одна или несколько групп из трёх цифр...
         (?!\d)     # которые не следуются никакими другими цифрами.
     )",

repl = \
    r"\1,",         # Заменить эту одну цифру на саму себя, добавив запятую,
                    # и продолжить поиск других совпадений в строке.
                    # (re.sub() заменяет все совпадения, найденные во входных данных)

string = \
    "%d" % val      # Изначальная строка форматируется как десятичное число
0

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

'{:,}'.format(value).replace(',', ваш_собственный_разделитель)

Примеры

'{:,.2f}'.format(123456789.012345).replace(',', ' ')

Если вам нужно представление в немецком стиле, то процесс становится немного более сложным:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # сохраняем разделители тысяч 
          .replace('.', ',')  # заменяем точку на запятую
          .replace(' ', '.')) # разделители тысяч заменяем на точку

Таким образом, вы можете легко настроить форматирование чисел под свои нужды.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь