将Python Decimal对象格式化为指定精度

17 投票
2 回答
27072 浏览
提问于 2025-04-17 17:05

我花了无数小时在研究、阅读和测试,最后感到困惑和失望,因为Python的Decimal对象在一个最基本的概念上缺乏支持:就是如何把Decimal的输出格式化成字符串。

假设我们有一些字符串或Decimal对象,它们的值如下:

   0.0008
  11.1111
 222.2222
3333.3333
1234.5678

我们的目标是简单地把Decimal的精度设置到小数点后两位。比如,11.1111应该格式化成11.11,而1234.5678则变成1234.57

我想要的代码大概是这样的:

import decimal
decimals = [
  decimal.Decimal('0.0008'),
  decimal.Decimal('11.1111'),
  decimal.Decimal('222.2222'),
  decimal.Decimal('3333.3333'),
  decimal.Decimal('1234.5678'),
]
for dec in decimals:
  print dec.as_string(precision=2, rounding=ROUND_HALF_UP)

最终的输出应该是:

0.00
11.11
222.22
3333.33
1234.57

显然,我们不能使用Decimal的上下文精度,因为它考虑的是数字的总位数,而不仅仅是小数的精度。

我也不想把Decimal转换成浮点数来输出它的值。使用Decimal的主要原因就是为了避免存储和计算浮点数。

还有其他解决方案吗?我知道在Stack Overflow上有很多类似的问题,但我没有找到能解决我所询问的根本问题的答案。

非常感谢!

2 个回答

2
def d(_in, decimal_places = 3):
    ''' Convert number to Decimal and do rounding, for doing calculations
        Examples:
          46.18271  to   46.183   rounded up
          46.18749  to   46.187   rounded down
          117.34999999999999 to 117.350
         _rescale is a private function, bad practice yet works for now.
    '''
    return Decimal(_in)._rescale(-decimal_places, 'ROUND_HALF_EVEN')

补充说明:再次强调,_rescale() 这个东西不是给我们普通人用的,它在 Python 2.7 中可以用,但在 3.4 版本中是没有的。

29

你可以使用字符串格式化或者format()函数来处理。

>>> for dec in decimals:
...    print format(dec, '7.2f')
... 
   0.00
  11.11
 222.22
3333.33
1234.57

decimal.Decimal支持和浮点数一样的格式规范,所以你可以根据需要使用科学计数法、固定小数点、通用格式、数字格式或百分比格式。

这是处理小数的官方且符合Python风格的方法;Decimal类实现了.__format__()方法,可以高效地处理这些格式化。

撰写回答