我如何区分格式化一个python十进制并保持其精度?

Chr*_*tin 13 python decimal

如何Decimal使用区域设置格式化?

为了通过示例来描述,我正在尝试定义一个函数f,使其在美国英语语言环境中:

  • f(Decimal('5000.00')) == '5,000.00'

  • f(Decimal('1234567.000000')) == '1,234,567.000000'

有些事情不起作用:

  • f = str 不使用区域设置; f(Decimal('5000.00')) == '5000.00'

  • f = lambda d: locale.format('%f', d) 不保留小数精度; f(Decimal('5000.00')) == '5000.000000'

  • f = lambda d: locale.format('%.2f', d) 使用固定的精度,这不是我追求的; f(Decimal('1234567.000000')) == '1234567.00'

Oz1*_*123 12

使用 Python 3.5+ 的现代 Python 方法是:

>>> import locale
>>> locale.setlocale(locale.LC_NUMERIC, "de_DE")
>>> f'{Decimal("5000.00"):n}'
'5.000,00'
>>> locale.setlocale(locale.LC_NUMERIC, "en_US")
'en_US'
>>> f'{Decimal("5000.00"):n}'
'5,000.00'
Run Code Online (Sandbox Code Playgroud)

F 字符串支持高级格式化。因此,不需要额外的f功能。Babel for Python会给你带来更多的便利:

>>> from babel import numbers
>>> numbers.format_decimal(.2345, locale='en_US')
'0.234'
>>> numbers.format_decimal(.2345, locale='de_DE')
'0,234'
 
Run Code Online (Sandbox Code Playgroud)


Rec*_*nic 7

通读该decimal模块的源代码,Decimal.__format__提供对PEP 3101的全面支持,您要做的就是选择正确的演示类型。在这种情况下,您需要:n类型。根据PEP 3101规范,它:n具有以下属性:

'n'-数字。这与'g'相同,只是它使用当前的语言环境设置来插入适当的数字分隔符。

这比其他答案更简单,并且避免了我原始答案中的浮点精度问题(保留在下面):

>>> import locale
>>> from decimal import Decimal
>>> 
>>> def f(d):
...     return '{0:n}'.format(d)
... 
>>> 
>>> locale.setlocale(locale.LC_ALL, 'en_us')
'en_us'
>>> print f(Decimal('5000.00'))
5,000.00
>>> print f(Decimal('1234567.000000'))
1,234,567.000000
>>> print f(Decimal('123456700000000.123'))
123,456,700,000,000.123
>>> locale.setlocale(locale.LC_ALL, 'no_no')
'no_no'
>>> print f(Decimal('5000.00'))
5.000,00
>>> print f(Decimal('1234567.000000'))
1.234.567,000000
>>> print f(Decimal('123456700000000.123'))
123.456.700.000.000,123
Run Code Online (Sandbox Code Playgroud)

原始错误答案

您可以告诉格式字符串使用十进制本身所包含的精度,并使用语言环境格式化程序:

def locale_format(d):
    return locale.format('%%0.%df' % (-d.as_tuple().exponent), d, grouping=True)
Run Code Online (Sandbox Code Playgroud)

请注意,如果您拥有一个与实数相对应的小数,该方法将起作用,但是如果该小数为NaN+Inf诸如此类,则无法正常工作。如果您的输入中有这些可能性,则需要在format方法中考虑它们。

>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale_format(Decimal('1234567.000000'))
'1,234,567.000000'
>>> locale_format(Decimal('5000.00'))
'5,000.00'
>>> locale.setlocale(locale.LC_ALL, 'no_no')
'no_no'
>>> locale_format(Decimal('1234567.000000'))
'1.234.567,000000'
>>> locale_format(Decimal('5000.00'))
'5.000,00'
>>> locale_format(Decimal('NaN'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in locale_format
TypeError: bad operand type for unary -: 'str'
Run Code Online (Sandbox Code Playgroud)