Ответ 1
Супер уродливый, но технически отвечает на вопрос:
От PEP 378:
'{:,}'.format(1234.56).replace(",", "X").replace(".", ",").replace("X", ".")
'1.234,56'
Я хочу форматировать целочисленные и плавающие числа в соответствии с немецким соглашением о нумерации. Это возможно с использованием языка форматирования и типа презентации n
, но сбой на моей платформе.
(v2.7.3:70274d53c1dd, Apr 9 2012, 20:52:43) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Примеры:
1234
= > 1.234
1234.56
= > 1.234,56
1000000
= > 1.000.000
То, что я пробовал до сих пор:
Настройка немецкого языка
import locale
locale.setlocale(locale.LC_ALL, 'de_DE')
Опция спецификации формата ,
распознает только английский формат.
'{:,}'.format(1234)
'1,234'
'{:,}'.format(1234.56)
'1,234.56'
'{:,}'.format(1000000)
'1,000,000'
В соответствии с документами Python, тип представления integer и float n
должен делать то, что я хочу, но это doesn "т.
'{:n}'.format(1234)
'1234'
'{:n}'.format(1234.56)
'1234,56' # at least the comma was set correctly here
'{:n}'.format(1000000)
'1000000'
'{:n}'.format(12345769.56)
'1,23458e+07' # it doing weird things for large floats
Еще несколько примеров и сравнений, вдохновленных @J.S.Sebastian:
for n in [1234, 1234.56, 1000000, 12345769.56]:
print('{0:,} {0:n}'.format(n))
fmt, val = "%d %f", (n, n)
print(fmt % val)
print(locale.format_string(fmt, val))
print(locale.format_string(fmt, val, grouping=True))
print('-'*60)
Это дает следующие неправильные результаты на моей платформе:
1,234 1234
1234 1234.000000
1234 1234,000000
1234 1234,000000
------------------------------------------------------------
1,234.56 1234,56
1234 1234.560000
1234 1234,560000
1234 1234,560000
------------------------------------------------------------
1,000,000 1000000
1000000 1000000.000000
1000000 1000000,000000
1000000 1000000,000000
------------------------------------------------------------
12,345,769.56 1,23458e+07
12345769 12345769.560000
12345769 12345769,560000
12345769 12345769,560000
------------------------------------------------------------
Правильные результаты, которые я не получаю, будут выглядеть так:
1,234 1.234
1234 1234.000000
1234 1234,000000
1.234 1.234,000000
------------------------------------------------------------
1,234.56 1.234,56
1234 1234.560000
1234 1234,560000
1.234 1.234,560000
------------------------------------------------------------
1,000,000 1.000.000
1000000 1000000.000000
1000000 1000000,000000
1.000.000 1.000.000,000000
------------------------------------------------------------
12,345,769.56 1,23458e+07
12345769 12345769.560000
12345769 12345769,560000
12.345.769 12.345.769,560000
------------------------------------------------------------
У вас есть решение для меня, используя только формат? Есть ли способ обмануть настройки языка на моей платформе, чтобы принять группировку?
Супер уродливый, но технически отвечает на вопрос:
От PEP 378:
'{:,}'.format(1234.56).replace(",", "X").replace(".", ",").replace("X", ".")
'1.234,56'
Это работало для меня при использовании с немецким языком:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
'de_DE'
>>> '{0:n}'.format(1234.56)
'1.234,56'
Это в Cygwin под Windows 7:
>>> import sys
>>> print sys.version
2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1]
Реализация модуля Python locale
, к сожалению, сильно различается на разных платформах. Это действительно просто легкая обертка вокруг понятия библиотеки поставщиков библиотеки C.
Итак, в Windows 7 с Python 2.7.3 64-разрядным это происходит, чтобы работать (обратите внимание: локали имеют разные имена в Windows):
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'deu_deu')
'German_Germany.1252'
>>> '{0:n}'.format(1234.56)
'1.234,56'
Будет ли использоваться разделитель тысяч, можно определить, "локальные соглашения" :
>>> locale.localeconv()['grouping'] # On Windows, 'deu_deu'.
[3, 0] # Insert separator every three digits.
>>> locale.localeconv()['grouping'] # On OS X, 'de_DE'.
[127] # No separator (locale.CHAR_MAX == 127).
>>> locale.localeconv()['grouping'] # Default C locale.
[] # Also no separator.
Я попросил @Lattyware предоставить мое собственное решение для включения разделителей в соответствии с немецким соглашением о нумерации без использования языка форматирования. Вот лучшее решение, которое я могу придумать:
import re
def group_num(num):
if isinstance(num, (int, float)):
if isinstance(num, float):
head, tail = str(num).split('.')
elif isinstance(num, int):
head, tail = str(num), ''
digit_parts = re.findall(r'\d{1,3}\-?', ''.join(head[::-1]))
num = '.'.join(part[::-1] for part in digit_parts[::-1])
if tail:
num = ','.join((num, tail))
return num
else:
raise TypeError(num, 'is not of type int or float')
>>> group_num(1234)
'1.234'
>>> group_num(123456.7890)
'123.456,789'
>>> group_num(-1000000000.12)
'-1.000.000.000,12'
Производительность также вполне удовлетворительная, по сравнению с решением, данным @Jon-Eric.
%timeit group_num(1000000000.12)
10000 loops, best of 3: 20.6 us per loop
# For integers, it faster since several steps are not necessary
%timeit group_num(100000000012)
100000 loops, best of 3: 18.2 us per loop
%timeit '{:,}'.format(1000000000.12).replace(",", "X").replace(".", ",").replace("X", ".")
100000 loops, best of 3: 2.63 us per loop
%timeit '{:,}'.format(100000000012).replace(",", "X").replace(".", ",").replace("X", ".")
100000 loops, best of 3: 2.01 us per loop
Если вы знаете, как мое решение может быть оптимизировано, сообщите мне.