小编典典

以工程格式打印编号

python

我正在尝试使用python将数字打印成工程格式,但似乎无法正常工作。SEEMS语法很简单,但是却行不通。

>>> import decimal 
>>> x = decimal.Decimal(1000000)
>>> print x
1000000
>>>> print x.to_eng_string() 
1000000

我不知道为什么会这样。这两个值不相等(一个是字符串,另一个是int)。设置各种上下文decimal似乎也无济于事。有任何线索或想法吗?


阅读 129

收藏
2020-12-20

共1个答案

小编典典

为了使它起作用,您必须先对小数进行归一化:

>>> x = decimal.Decimal ('10000000')

>>> x.normalize()
Decimal('1E+7')

>>> x.normalize().to_eng_string()
'10E+6'

可以通过深入研究源代码来发现其原因。

如果您检查to_eng_string()在Python
2.7.3源代码树(Lib/decimal.py从gzip压缩的源焦油球在这里),它只是简单地调用__str__eng设置为true。

然后,您可以看到它决定了最初使用十进制小数点左边的位数:

leftdigits = self._exp + len(self._int)

下表显示了这两件事的值:

                         ._exp       ._int         len   leftdigits
                         -----       ---------     ---   ----------
Decimal (1000000)            0       '1000000'       7            7
Decimal ('1E+6')             6       '1'             1            7

此后继续的代码是:

if self._exp <= 0 and leftdigits > -6:
    # no exponent required
    dotplace = leftdigits
elif not eng:
    # usual scientific notation: 1 digit on left of the point
    dotplace = 1
elif self._int == '0':
    # engineering notation, zero
    dotplace = (leftdigits + 1) % 3 - 1
else:
    # engineering notation, nonzero
    dotplace = (leftdigits - 1) % 3 + 1

并且您会看到,除非它已经 具有 一定范围内的指数(self._exp > 0 or leftdigits <= -6),否则在字符串表示形式中将不会给出任何指数。


进一步的调查显示了这种行为的原因。查看代码本身,您将看到它基于General Decimal Arithmetic Specification此处的PDF
)。

如果您搜索该文档to-scientific-string(基于文档to-engineering-string),则部分说明(措辞并加粗体):

如果需要指数 ,“ to-scientific-string”操作会将数字转换为字符串,并使用科学计数法 该操作不受上下文的影响。

如果该数字是有限数,则:

该系数首先使用从0到9的字符转换为以10为底的字符串,且不带前导零(除非其值为零,在这种情况下使用单个0字符)。

接下来,计算调整后的指数。这是指数,加上转换系数中的字符数,再减去一个。也就是说,指数+(clength-1),其中clength是系数的长度(以十进制数字表示)。

如果指数小于或等于零,并且调整后的指数大于或等于-6,则数字将转换为字符形式而无需使用指数表示法。
在这种情况下,如果指数为零,则不添加小数点。否则(指数为负),将插入一个小数点,该指数的绝对值指定小数点右边的字符数。必要时,将“
0”字符添加到转换系数的左侧。如果在插入后小数点之前没有字符,则以常规的“ 0”字符为前缀。

换句话说,它正在做它正在做的事情,因为这就是标准告诉它要做的事情。

2020-12-20