获取Python十进制的精确十进制字符串表示形式? [英] Get precise decimal string representation of Python Decimal?

查看:112
本文介绍了获取Python十进制的精确十进制字符串表示形式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如,如果我有:

 >>> ; d =小数('1e-14')

我想要:

 >> get_decimal_string(d)
'0.00000000000001'

但是:


  1. 十进制类没有任何 to_decimal_string 方法,甚至任何 to_radix_string(radix)(cf: https://docs.python.org/3/library/decimal.html#decimal.Context.to_eng_string

  2. The %f 格式化程序默认默认舍入到小数点后6位-'%f'%(d,)==> '0.000000'-或要求精确的小数位数。

  3. {:f} .format(...)格式化程序出现起作用-'{:f}'。format(d)
    ==> '0.00000000000001'
    -但是我不愿意相信这一点,因为这实际上与文档,其中显示 'f'…显示为固定数字,点精度。默认精度为6

  4. 十进制。__repr __ 十进制。__str __ 有时返回科学计数法: repr(d)==> Decimal('1E-14')

因此,有什么方法可以获取小数Python 十进制中的字符串?还是我需要使用 Decimal.as_tuple()自己滚动?

解决方案

简短答案:



 >> d 
小数('1E-14')
>>> '{:f}'。format(d)
'0.00000000000001'



长答案:



布兰登罗兹指出的 PEP 3101 (PEP的字符串格式)状态:


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


因此, Decimal .__ format __ 方法是python的字符串格式将用来生成<$ 十进制值的c $ c> str 表示形式。基本上十进制会将格式覆盖为智能格式,但默认为格式字符串设置的任何值(即 {:. 4f} 会将小数位截断为4位。



这就是为什么您可以信任它(摘录自 decimal.py:Decimal .__ format __ ):

  def __format __(self,specifier,context = None, _localeconv = None):

#...实施被截断


#找出小数点的位置
leftdigits = self._exp + len(self._int)
如果spec ['type']在' eE':
如果不是self且精度不为None:
dotplace = 1-精度
else:
dotplace = 1
elif spec ['type'] in 'fF%':
dotplace =左位数
elif spec ['type'] in'gG':
if self._exp< = 0且左位数> -6:
dotplace =左位数
else:
dotplace = 1

#查找小数点前后的数字,如果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]或'0'
fracpart = self._int [dotplace:]
exp = leftdigits-dotplace

#用十进制特定的东西完成;将格式的其余
#交给_format_number函数
返回_format_number(self._sign,intpart,fracpart,exp,spec)

长话短说, Decimal .__ format __ 方法将计算必要的填充,以表示小数点前后的数字基于 Decimal._exp 提供的幂运算(在您的示例中为14个有效数字)。

 >> d._exp 
-14


If I've got a Python Decimal, how can I reliably get the precise decimal string (ie, not scientific notation) representation of the number without trailing zeros?

For example, if I have:

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

I would like:

>>> get_decimal_string(d)
'0.00000000000001'

However:

  1. The Decimal class doesn't have any to_decimal_string method, or even any to_radix_string(radix) (cf: https://docs.python.org/3/library/decimal.html#decimal.Context.to_eng_string)
  2. The %f formatter either defaults to rounding to 6 decimal places - '%f' %(d, ) ==> '0.000000' - or requires a precise number of decimal places.
  3. The {:f}.format(...) formatter appears to work - '{:f}'.format(d) ==> '0.00000000000001' - however I'm reluctant to trust that, as this actually runs counter to the documentation, which says "'f' … Displays the number as a fixed-point number. The default precision is 6"
  4. Decimal.__repr__ and Decimal.__str__ sometimes return scientific notation: repr(d) ==> "Decimal('1E-14')"

So, is there any way to get a decimal string from a Python Decimal? Or do I need to roll my own using Decimal.as_tuple()?

解决方案

Short answer:

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

Long answer:

As Brandon Rhodes pointed out PEP 3101 (which is the string format PEP) states:

The syntax for format specifiers is open-ended, since a class can override the standard format specifiers. In such cases, the str.format() method merely passes all of the characters between the first colon and the matching brace to the relevant underlying formatting method.

And thus, the Decimal.__format__ method is what python's string format will utilize to generate the str representation of the Decimal value. Basically Decimal overrides the formatting to be "smart" but will default to whatever values the format string sets (ie {:.4f} will truncate the decimal to 4 places).

Here's why you can trust it (snippet from 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)

Long story short, the Decimal.__format__ method will calculate the necessary padding to represent the number before and after the decimal based upon exponentiation provided from Decimal._exp (in your example, 14 significant digits).

>>> d._exp
-14

这篇关于获取Python十进制的精确十进制字符串表示形式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆