问题
Update: The answers show so far that it seems to be a platform-related bug on OSX that has to do with the specific locale settings as they don't fully support grouping numbers.
Update 2: I have just opened an issue on Python's bug tracker. Let's see if there is a solution to this problem.
I want to format integer and float numbers according to the German numbering convention. This is possible using the format language and the presentation type n
but fails on my platform.
- Platform: OS X 10.8.2 (Mountain Lion)
- Python: 2.7.3 64-bit
(v2.7.3:70274d53c1dd, Apr 9 2012, 20:52:43) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Examples:
1234
=>1.234
1234.56
=>1.234,56
1000000
=>1.000.000
What I have tried so far:
Setting the German locale
import locale locale.setlocale(locale.LC_ALL, 'de_DE')
The format specification option
,
only recognizes the English format.'{:,}'.format(1234) '1,234' '{:,}'.format(1234.56) '1,234.56' '{:,}'.format(1000000) '1,000,000'
According to the Python docs, the integer and float presentation type
n
is supposed to do what I want but it doesn't.'{: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's doing weird things for large floats
Some more examples and comparisons inspired by @J.F.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)
This yields the following incorrect results on my platform:
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 ------------------------------------------------------------
The correct results which I'm not getting would look like that:
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 ------------------------------------------------------------
Do you have a solution for me using the format language only? Is there any way to trick the locale settings on my platform to accept grouping?
回答1:
Super ugly, but technically answers the question:
From PEP 378:
'{:,}'.format(1234.56).replace(",", "X").replace(".", ",").replace("X", ".")
'1.234,56'
回答2:
Python's locale
module's implementation unfortunately varies quite a bit across platforms. It's really just a light wrapper around the C library vendor's notion of locales.
So, on Windows 7, with Python 2.7.3 64-bit, this happens to work (note: locales have different names in Windows):
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'deu_deu')
'German_Germany.1252'
>>> '{0:n}'.format(1234.56)
'1.234,56'
Whether the thousands separator will be used can be determined by examining the "local conventions":
>>> 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.
回答3:
This worked for me when used with the German locale:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
'de_DE'
>>> '{0:n}'.format(1234.56)
'1.234,56'
This is in Cygwin under 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]
回答4:
I was asked by @Lattyware to provide my own solution for including separators according to the German numbering convention without using the format language. Here is the best solution that I can come up with:
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'
The performance is also quite okay, compared to the solution given by @Jon-Eric.
%timeit group_num(1000000000.12)
10000 loops, best of 3: 20.6 us per loop
# For integers, it's 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
If you know how my solution could be optimized, please let me know.
回答5:
Even more ugly with split
, join
and replace
:
>>> amount = '{0:,}'.format(12345.67)
>>> amount
'12,345.67'
>>> ','.join([s.replace(',','.') for s in amount.split('.')])
'12.345,67'
来源:https://stackoverflow.com/questions/14287051/german-number-separators-using-format-language-on-osx