以工程格式打印编号

时间:2012-09-07 03:00:22

标签: python python-2.7 decimal

我试图用python将数字打印成工程格式,但我似乎无法让它工作。语法SEEMS足够简单,但它不起作用。

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

我无法弄清楚为什么会这样。这两个值不相等(一个是字符串,另一个是int)。在decimal中设置各种上下文似乎也没有帮助。任何线索或想法?

8 个答案:

答案 0 :(得分:21)

要使其正常工作,您必须首先将小数标准化:

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

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

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

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

如果您检查Python 2.7.3源代码树中的to_eng_string()(来自gzip压缩源tar球hereLib/decimal.py),则只需使用{{1}调用__str__设置为true。

然后,您可以看到它决定了最初使用小数点左边有多少位数:

eng

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

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 ),否则在字符串表示中都不会给它。


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

如果你搜索self._exp > 0 or leftdigits <= -6的文件(to-scientific-string严重依据的话),它会部分说明(转述,并用我的粗体位):

  

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

     

如果数字是有限数,那么:

     

系数首先使用字符0到9转换为十进制字符串,不带前导零(除非它的值为零,在这种情况下使用单个0字符)。

     

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

     

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

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

答案 1 :(得分:7)

我意识到这是一个旧线程,但它确实接近搜索python engineering notation的顶部。

我是一名喜欢“工程101”工程单位的工程师。我甚至不喜欢0.1uF这样的名称,我想要阅读100nF。我使用Decimal类并且并不喜欢它在可能值范围内的行为,因此我推出了一个名为engineering_notation的可以进行pip安装的包。

pip install engineering_notation

从Python中:

>>> from engineering_notation import EngNumber
>>> EngNumber('1000000')
1M
>>> EngNumber(1000000)
1M
>>> EngNumber(1000000.0)
1M
>>> EngNumber('0.1u')
100n
>>> EngNumber('1000m')
1

该软件包还支持比较和其他简单的数值运算。

https://github.com/slightlynybbled/engineering_notation

答案 2 :(得分:4)

在我看来,你将不得不自己动手:

from math import log10
def eng_str(x):
    y = abs(x)
    exponent = int(log10(y))
    engr_exponent = exponent - exponent%3
    z = y/10**engr_exponent
    sign = '-' if x < 0 else ''
    return sign+str(z)+'e'+str(engr_exponent)

虽然您可能需要更加关注z部分的格式......

未经过充分测试。如果发现错误,请随时编辑

答案 3 :(得分:0)

QuantiPhy是另一个可以帮助您解决此问题的软件包。 QuantiPhy 提供了 Quantity 类,该类用于将值和单位组合为一个对象。它可以通过多种方式格式化数量。通常,人们使用SI比例因子,但也支持工程形式。安装方式:

pip3 install quantiphy

您可以从数字或字符串开始创建 Quantity 对象:

>>> from quantiphy import Quantity
>>> q = Quantity(10000000)
>>> q.render(form='eng')
'10e6'

默认情况下, QuantiPhy 使用SI表示法,但是您可以将默认格式设置为“ eng”:

>>> print(q)
10M
>>> Quantity.set_prefs(form='eng')
>>> print(q)
10e6

通常,您要为数量指定单位:

>>> f = Quantity(10_000_000, 'Hz')
>>> print(f)
10e6 Hz

数量子类是 float ,因此您可以在任何使用浮点的地方使用数量。

QuantiPhy 是一个功能强大的程序包,得到了很好的支持和详细记录。我鼓励您尝试一下。

答案 4 :(得分:0)

matplotlib 也可以使用:

>>> from matplotlib.ticker import EngFormatter
>>> engFormat = EngFormatter()
>>> print(engFormat(1000))
1 k

我让您在 https://matplotlib.org/stable/api/ticker_api.html 上查看更多详细信息和选项 另一个更复杂的例子:

>>> from matplotlib.ticker import EngFormatter
>>> engFormat = EngFormatter(unit='Hz',places=2,sep='')
>>> print(engFormat(1000))
1.00kHz

答案 5 :(得分:0)

有一个使用内置 printf-style String Formatting

的解决方案

我将假设(及时向前)您现在使用内置的 python 3,因为所有格式化都大大简化和规范化(我建议将 this cheat sheet 添加为书签。

In [1]: myfloat = 0.000000001
In [2]: print(f'{myfloat:g}')
1e-09

较旧的语法(适用于 python 2)是:

In [17]: '%g' % myfloat
Out[17]: '1e-09'

另一种不错的格式是:

In [3]: print(f'{myfloat:E}')
1.000000E-09

您可以对其输出进行一些控制:

In [4]: print(f'{myfloat:.3E}')
1.000E-09

答案 6 :(得分:-1)

以前我试过回答,但发现它仍然是科学记数法。 Python格式说明符(3.2?)的未来版本将支持工程符号,但Python 2.7中不支持。

请看这个问题http://bugs.python.org/issue8060

答案 7 :(得分:-1)

现在是2020年!并且发生了COVID-19大流行。对于这种类型的工作,您必须使用f字符串文字:

使用python3.6.4及更高版本,您可以

git merge upstream/master