获取Python十进制的精确十进制字符串表示形式?


问题内容

如果我有Python Decimal,如何才能可靠地获取数字的精确十进制字符串(即,不是科学计数法)表示形式而不尾随零?

例如,如果我有:

>>> d = Decimal('1e-14')

我想要:

>>> get_decimal_string(d)
'0.00000000000001'

然而:

  1. Decimal类没有任何to_decimal_string方法,甚至任何to_radix_string(radix)(参见:https://docs.python.org/3/library/decimal.html#decimal.Context.to_eng_string
  2. 所述%f格式化器缺省为四舍五入至小数点后6位- '%f' %(d, ) ==> '0.000000'-或需要小数位的精确数量。
  3. {:f}.format(...)格式 出现 工作- '{:f}'.format(d) ==> '0.00000000000001'- 我不愿意相信,因为这实际上是背道而驰的文件,它说“ 'f'…显示为固定点数数的默认精度为6位。”
  4. Decimal.__repr__并且Decimal.__str__有时返回科学记数法:repr(d) ==> "Decimal('1E-14')"

那么,有什么方法可以从Python获取十进制字符串Decimal吗?还是我需要自己动手使用Decimal.as_tuple()


问题答案:

简短答案:

>>> d
Decimal('1E-14')
>>> '{:f}'.format(d)
'0.00000000000001'

长答案:

正如布兰登·罗德斯Brandon
Rhodes)
指出的,PEP
3101
(这是字符串格式PEP)指出:

格式说明符的语法是开放式的,因为类可以覆盖标准格式说明符。在这种情况下,str.format()方法仅将第一个冒号和匹配括号之间的所有字符传递给相关的基础格式设置方法。

因此,该Decimal.__format__方法是python的字符串格式将用来生成值str表示形式的方法Decimal。基本上Decimal将格式覆盖为“智能”格式,但默认使用格式字符串设置的任何值(即,{:.4f}将小数位截断为4位)。

您可以信任它的原因(来自的片段decimal.py:Decimal.__format__):

def __format__(self, specifier, context=None, _localeconv=None):
    #
    # ...implementation snipped.
    #

    # figure out placement of the decimal point
    leftdigits = self._exp + len(self._int)
    if spec['type'] in 'eE':
        if not self and precision is not None:
            dotplace = 1 - precision
        else:
            dotplace = 1
    elif spec['type'] in 'fF%':
        dotplace = leftdigits
    elif spec['type'] in 'gG':
        if self._exp <= 0 and leftdigits > -6:
            dotplace = leftdigits
        else:
            dotplace = 1

    # find digits before and after decimal point, and get exponent
    if dotplace < 0:
        intpart = '0'
        fracpart = '0'*(-dotplace) + self._int
    elif dotplace > len(self._int):
        intpart = self._int + '0'*(dotplace-len(self._int))
        fracpart = ''
    else:
        intpart = self._int[:dotplace] or '0'
        fracpart = self._int[dotplace:]
    exp = leftdigits-dotplace

    # done with the decimal-specific stuff;  hand over the rest
    # of the formatting to the _format_number function
    return _format_number(self._sign, intpart, fracpart, exp, spec)

长话短说,该Decimal.__format__方法将根据提供的幂Decimal._exp(在您的示例中为14个有效数字)来计算必要的填充,以表示小数点之前和之后的数字。

>>> d._exp
-14