这是困扰我的例子:
>>> x = decimal.Decimal('0.0001')
>>> print x.normalize()
>>> print x.normalize().to_eng_string()
0.0001
0.0001
有没有办法用工程符号来表示 mili (10e-3) 和 micro (10e-6)?
这是困扰我的例子:
>>> x = decimal.Decimal('0.0001')
>>> print x.normalize()
>>> print x.normalize().to_eng_string()
0.0001
0.0001
有没有办法用工程符号来表示 mili (10e-3) 和 micro (10e-6)?
这是一个明确执行操作的函数,并且还支持对指数使用 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)
编辑: Matplotlib 实现了工程格式化程序,因此一种选择是直接使用 Matplotlibs 格式化程序,例如:
import matplotlib as mpl
formatter = mpl.ticker.EngFormatter()
formatter(10000)
result: '10 k'
原答案:
基于 Julian Smith 的出色回答(以及这个回答),我更改了函数以改进以下几点:
所以这里是更新的功能:
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)
该decimal
模块遵循Decimal Arithmetic Specification,其中指出:
to-scientific-string – 转换为数字字符串
[...]
首先将系数转换为以 10 为底的字符串,使用字符 0 到 9,不带前导零(除非它的值为零,在这种情况下使用单个 0 字符)。接下来,计算调整后的指数;这是指数加上转换系数中的字符数减去一。也就是说,exponent+(clength-1),其中 clength 是十进制数字的系数长度。
如果指数小于或等于 0 且调整后的指数大于或等于 -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
我意识到这是一个旧线程,但它确实接近搜索的顶部,python engineering notation
并且将这些信息放在此处似乎是谨慎的。
我是一个喜欢“工程101”工程单元的工程师。我什至不喜欢诸如0.1uF
, I want that read之类的名称100nF
。我玩过这个Decimal
类,并不喜欢它在可能值范围内的行为,所以我推出了一个名为engineering_notation
pip-installable 的包。
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
这个包还支持比较和其他简单的数值运算。
该decimal
模块确实遵循专有的(IBM)十进制算术规范。完整
引用这个 IBM 规范清楚地表明了问题所在decimal.to_eng_string()
(添加了重点):
to-engineering-string – 转换为数字字符串
此操作将数字转换为字符串,如果需要指数,则使用工程符号。
转换完全遵循转换为科学数字字符串的规则,但使用指数表示法的有限数除外。在这种情况下,通过在小数点前面放置一个、两个或三个字符(即,小数点前面的部分将在 1 到 999 之间) ,将转换后的指数调整为三的倍数(工程符号))。这可能需要添加一个或两个尾随零。
如果调整后小数点后面没有数字,则不添加。如果最终指数为零,则没有指示字母和指数后缀。
这个专有的 IBM 规范实际上承认不对具有无限十进制表示的数字应用工程符号,而是使用普通的科学记数法!这显然是打开Python 错误报告的不正确行为。
from math import floor, log10
def powerise10(x):
""" Returns x as a*10**b with 0 <= a < 10
"""
if x == 0: return 0,0
Neg = x < 0
if Neg: x = -x
a = 1.0 * x / 10**(floor(log10(x)))
b = int(floor(log10(x)))
if Neg: a = -a
return a,b
def eng(x):
"""Return a string representing x in an engineer friendly notation"""
a,b = powerise10(x)
if -3 < b < 3: return "%.4g" % x
a = a * 10**(b % 3)
b = b - b % 3
return "%.4gE%s" % (a,b)
来源:https ://code.activestate.com/recipes/578238-engineering-notation/
>>> eng(0.0001)
100E-6
像上面的答案一样,但更紧凑:
from math import log10, floor
def eng_format(x,precision=3):
"""Returns string in engineering format, i.e. 100.1e-3"""
x = float(x) # inplace copy
if x == 0:
a,b = 0,0
else:
sgn = 1.0 if x > 0 else -1.0
x = abs(x)
a = sgn * x / 10**(floor(log10(x)))
b = int(floor(log10(x)))
if -3 < b < 3:
return ("%." + str(precision) + "g") % x
else:
a = a * 10**(b % 3)
b = b - b % 3
return ("%." + str(precision) + "gE%s") % (a,b)
审判:
In [10]: eng_format(-1.2345e-4,precision=5)
Out[10]: '-123.45E-6'