繁体   English   中英

在OSX上使用格式语言的德语数字分隔符?

[英]German number separators using format language on OSX?

更新:答案显示到目前为止它似乎是OSX上与平台相关的错误,它与特定的区域设置有关,因为它们不完全支持分组编号。

更新2:我刚刚在Python的bug跟踪器上打开了一个问题 让我们看看是否有解决此问题的方法。


我想根据德语编号约定格式化整数和浮点数。 这可以使用格式语言和表示类型n但在我的平台上失败。

  • 平台:OS X 10.8.2(Mountain Lion)
  • Python:2.7.3 64位(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

到目前为止我尝试了什么:

  1. 设置德语区域设置

     import locale locale.setlocale(locale.LC_ALL, 'de_DE') 
  2. 格式规范选项,只能识别英文格式。

     '{:,}'.format(1234) '1,234' '{:,}'.format(1234.56) '1,234.56' '{:,}'.format(1000000) '1,000,000' 
  3. 根据Python文档 ,整数和浮动表示类型n应该做我想要的但却没有。

      '{: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 
  4. 由@JFSebastian启发的更多示例和比较:

     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'

不幸的是,Python的locale模块的实现在不同平台上有很大差异。 它实际上只是围绕C库供应商的语言环境概念的一个轻量级包装器。

因此,在Windows 7上,使用64位的Python 2.7.3,这恰好可行(注意: locales在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.

当与德语语言环境一起使用时,这对我有用:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
'de_DE'
>>> '{0:n}'.format(1234.56)
'1.234,56'

这是在Windows 7下的Cygwin中:

>>> import sys
>>> print sys.version
2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1]

@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'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

如果您知道我的解决方案如何优化,请告诉我。

splitjoinreplace更加丑陋:

>>> amount = '{0:,}'.format(12345.67)
>>> amount
'12,345.67'
>>> ','.join([s.replace(',','.') for s in amount.split('.')])
'12.345,67'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM