Python Decimal - mili(10e-3)和micro(10e-6)的工程符号

The*_*eer 10 python decimal python-2.7

这是困扰我的例子:

>>> x = decimal.Decimal('0.0001')
>>> print x.normalize()
>>> print x.normalize().to_eng_string()
0.0001
0.0001
Run Code Online (Sandbox Code Playgroud)

有没有办法用表示mili(10e-3)和micro(10e-6)的工程符号?

小智 11

这是一个明确地执行操作的函数,并且还支持为指数使用SI后缀:

def eng_string( x, format='%s', si=False):
    '''
    Returns float/int value <x> formatted in a simplified engineering format -
    using an exponent that is a multiple of 3.

    format: printf-style string used to format the value before the exponent.

    si: if true, use SI suffix for exponent, e.g. k instead of e3, n instead of
    e-9 etc.

    E.g. with format='%.2f':
        1.23e-08 => 12.30e-9
             123 => 123.00
          1230.0 => 1.23e3
      -1230000.0 => -1.23e6

    and with si=True:
          1230.0 => 1.23k
      -1230000.0 => -1.23M
    '''
    sign = ''
    if x < 0:
        x = -x
        sign = '-'
    exp = int( math.floor( math.log10( x)))
    exp3 = exp - ( exp % 3)
    x3 = x / ( 10 ** exp3)

    if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0:
        exp3_text = 'yzafpnum kMGTPEZY'[ ( exp3 - (-24)) / 3]
    elif exp3 == 0:
        exp3_text = ''
    else:
        exp3_text = 'e%s' % exp3

    return ( '%s'+format+'%s') % ( sign, x3, exp3_text)
Run Code Online (Sandbox Code Playgroud)

  • 还有两个建议:对于 python3,我们需要显式地进行整数除法,因此 'yzafpnum kMGTPEZY'[ exp3 // 3 + 8] 对于 x=0,我们需要一个类似 if x==0: exp=0 的情况,exp3=0 (3认同)

Zer*_*eus 6

decimal模块遵循“ 十进制算术规范”,该规范指出:

to-scientific-string –转换为数字字符串

[...]

该系数首先使用从0到9的字符转换为以10为底的字符串,且不带前导零(除非其值为零,在这种情况下使用单个0字符)。接下来,计算调整后的指数。这是指数,再加上转换系数中的字符数,再减去一个。也就是说,指数+(clength-1),其中clength是系数的长度(以十进制数字表示)。

如果指数小于或等于零,并且调整后的指数大于或等于-6,则数字将转换为字符形式,而无需使用指数表示法。

[...]

to-engineering-string –转换为数字字符串

如果需要指数,此操作将使用工程符号将数字转换为字符串。

转换完全遵循转换为科学数字字符串的规则,除非使用指数表示法的有限数字除外。

或者,换句话说:

>>> for n in (10 ** e for e in range(-1, -8, -1)):
...     d = Decimal(str(n))
...     print d.to_eng_string()
... 
0.1
0.01
0.001
0.0001
0.00001
0.000001
100E-9
Run Code Online (Sandbox Code Playgroud)


pop*_*pie 5

编辑: Matplotlib实现了工程格式化程序,因此一种选择是直接使用Matplotlibs格式化程序,例如:

import matplotlib as mpl
formatter = mpl.ticker.EngFormatter()
formatter(10000)

result: '10 k'
Run Code Online (Sandbox Code Playgroud)

原始答案:

基于朱利安·史密斯(Julian Smith)的出色答案(以及答案),我更改了功能以改进以下几点:

  • 兼容Python3(整数除法)
  • 兼容0输入
  • 舍入到有效位数,默认为3,不打印尾随零

所以这是更新的功能:

import math
def eng_string( x, sig_figs=3, si=True):
    """
    Returns float/int value <x> formatted in a simplified engineering format -
    using an exponent that is a multiple of 3.

    sig_figs: number of significant figures

    si: if true, use SI suffix for exponent, e.g. k instead of e3, n instead of
    e-9 etc.
    """
    x = float(x)
    sign = ''
    if x < 0:
        x = -x
        sign = '-'
    if x == 0:
        exp = 0
        exp3 = 0
        x3 = 0
    else:
        exp = int(math.floor(math.log10( x )))
        exp3 = exp - ( exp % 3)
        x3 = x / ( 10 ** exp3)
        x3 = round( x3, -int( math.floor(math.log10( x3 )) - (sig_figs-1)) )
        if x3 == int(x3): # prevent from displaying .0
            x3 = int(x3)

    if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0:
        exp3_text = 'yzafpnum kMGTPEZY'[ exp3 // 3 + 8]
    elif exp3 == 0:
        exp3_text = ''
    else:
        exp3_text = 'e%s' % exp3

    return ( '%s%s%s') % ( sign, x3, exp3_text)
Run Code Online (Sandbox Code Playgroud)


sli*_*led 5

我意识到这是一个旧线程,但是它确实在搜索的顶部附近python engineering notation,因此在此处找到此信息似乎是审慎的做法。

我是一位喜欢“ engineering 101”工程单位的工程师。我什至不喜欢这样的称呼0.1uF,我想读一下100nF。我玩过Decimal该类,但实际上并不喜欢它在可能的值范围内的行为,因此我推出了一个名为engineering_notationpip-installable 的软件包。

pip install engineering_notation
Run Code Online (Sandbox Code Playgroud)

从Python内部:

>>> from engineering_notation import EngNumber
>>> EngNumber('1000000')
1M
>>> EngNumber(1000000)
1M
>>> EngNumber(1000000.0)
1M
>>> EngNumber('0.1u')
100n
>>> EngNumber('1000m')
1
Run Code Online (Sandbox Code Playgroud)

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

https://github.com/slightlynybbled/engineering_notation