Как вывести число с разделением тысяч запятыми
Как напечатать целое число с запятыми в качестве разделителей тысяч?
У меня есть целое число, например, 1234567
, и мне нужно отформатировать его так, чтобы оно отображалось с запятыми в качестве разделителей тысяч, то есть 1,234,567
.
Важно, чтобы форматирование не зависело от локали и не принимало во внимание разницу между запятыми и точками.
Как я могу реализовать это в своем коде?
5 ответ(ов)
Я смог это сделать следующим образом:
>>> 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
.
Для неэффективности и трудночитаемости это трудно превзойти:
>>> 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
возвращает многообещающий, но сложный в понимании результат. Если вы стремитесь к более читаемому и более эффективному решению, стоит рассмотреть альтернативные подходы, такие как использование более простых списков или функций для обработки строк.
Вот что я делаю для форматирования чисел с плавающей точкой. Хотя, если честно, я не уверен, для каких версий это работает — я использую 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)
Теперь все работает корректно.
Вот однострочное решение для замены с помощью регулярных выражений:
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 # Изначальная строка форматируется как десятичное число
Если вы хотите использовать свой собственный разделитель тысяч, то самым простым решением будет следующее:
'{:,}'.format(value).replace(',', ваш_собственный_разделитель)
Примеры
'{:,.2f}'.format(123456789.012345).replace(',', ' ')
Если вам нужно представление в немецком стиле, то процесс становится немного более сложным:
('{:,.2f}'.format(123456789.012345)
.replace(',', ' ') # сохраняем разделители тысяч
.replace('.', ',') # заменяем точку на запятую
.replace(' ', '.')) # разделители тысяч заменяем на точку
Таким образом, вы можете легко настроить форматирование чисел под свои нужды.
Почему используется string.join(list), а не list.join(string)?
Создание словаря с помощью генератора словарей
Как получить полный путь к директории текущего файла?
UnicodeDecodeError: Кодек 'charmap' не может декодировать байт X в позиции Y: символ отображается как <неопределённый>
Найти все файлы с расширением .txt в директории на Python