如果我有Python Decimal
,如何可靠地获取数字的精确十进制字符串(即,不是科学计数法)表示形式而不尾随零?
例如,如果我有:
>>> d = Decimal('1e-14')
我想要:
>>> get_decimal_string(d)
'0.00000000000001'
但是:
Decimal
类没有任何to_decimal_string
方法,甚至没有任何to_radix_string(radix)
(参见:https://docs.python.org/3/library/decimal.html#decimal.Context.to_eng_string)%f
格式器默认舍入到小数点后6位-'%f' %(d, ) ==> '0.000000'
-或要求精确的小数位数。{:f}.format(...)
格式化程序似乎可以工作-'{:f}'.format(d)
==> '0.00000000000001'
-但是我不愿意相信这一点,因为这实际上与{ {3}},它表示“ 'f'
…将数字显示为定点数字。默认精度为6” Decimal.__repr__
和Decimal.__str__
有时会返回科学符号:repr(d) ==> "Decimal('1E-14')"
那么,有什么方法可以从Python Decimal
获取十进制字符串吗?还是我需要使用Decimal.as_tuple()
自己滚动?
答案 0 :(得分:5)
>>> d
Decimal('1E-14')
>>> '{:f}'.format(d)
'0.00000000000001'
@BrandonRhodes指出PEP 3101(这是字符串格式PEP)指出:
格式说明符的语法是开放式的,因为类可以 覆盖标准格式说明符。在这种情况下, str.format()方法仅在两个字符之间传递所有字符。 第一个冒号和与之相关的括号 格式化方法。
因此,Decimal.__format__
方法是python的字符串格式将用来生成str
值的Decimal
表示形式的方法。基本上Decimal
会将格式覆盖为“智能”格式,但默认使用格式字符串设置的任何值(即{:.4f}
会将小数位截断为4位)。
这就是为什么您可以信任它(来自decimal.py:Decimal.__format__
的片段):
# PEP 3101 support. the _localeconv keyword argument should be
# considered private: it's provided for ease of testing only.
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