我正在寻找一个带有支持在不同SI前缀之间转换数字的Python库,例如千分之一至皮秒、纳秒至吉赫等等。你有什么推荐吗?
您可以通过以下方式安装:
pip install si-prefix
源代码可以在 GitHub 上获取。
使用示例:
from si_prefix import si_format
print si_format(.5)
# 500.0m (default precision is 1)
print si_format(.01331, precision=2)
# 13.31m
print si_format(1331, precision=2)
# 1.33k
print si_format(1331, precision=0)
# 1k
QuantiPhy 是一个新的软件包,可以将数字转换为SI比例因子,并从中进行转换。与重量更大且专注于单位而非比例因子的Unit和Magnitude等单位软件包相比,它通常是更好的选择。
QuantiPhy提供了Quantity,这是一个将数字与其度量单位结合(单位可选)的对象。在创建数量时,您可以使用SI单位前缀。一旦您拥有了Quantity,您可以在表达式中使用它,它会作为浮点数。或者您可以将其转换为字符串,在这种情况下,默认使用SI单位前缀。
>>> from quantiphy import Quantity
# convert strings to quantities
>>> duration = Quantity('0.12 ks')
>>> print(duration)
120 s
# convert to other units when rendering to a string
>>> print(duration.render(scale='min'))
2 min
# quantities act like floats in expressions
>>> rate = 1/duration
>>> print(rate)
0.008333333333333333
# convert floats to quantities
>>> rate = Quantity(rate, 'Hz')
>>> print(rate)
8.3333 mHz
# can be used in format strings
>>> print(f'Duration = {duration:<12.3} Rate = {rate}')
Duration = 120 s Rate = 8.3333 mHz
>>> mass = Quantity('1000 g')
>>> print(mass)
1 kg
>>> print(mass.render(show_si=False))
1e3 g
>>> print(mass.render(show_si=False, scale=(1e-12, 'pg')))
1e9 pg
>>> l = Quantity('2um')
>>> print(l.render(scale='Å'))
20 kÅ
>>> print(f'{l:sÅ}')
20 kÅ
如果您不想使用下面列出的任何第三方库,实际上可以自己实现解析功能。
使用字典将前缀与其值匹配。我已经为您完成了:
_prefix = {'y': 1e-24, # yocto
'z': 1e-21, # zepto
'a': 1e-18, # atto
'f': 1e-15, # femto
'p': 1e-12, # pico
'n': 1e-9, # nano
'u': 1e-6, # micro
'm': 1e-3, # mili
'c': 1e-2, # centi
'd': 1e-1, # deci
'k': 1e3, # kilo
'M': 1e6, # mega
'G': 1e9, # giga
'T': 1e12, # tera
'P': 1e15, # peta
'E': 1e18, # exa
'Z': 1e21, # zetta
'Y': 1e24, # yotta
}
接下来您可以使用正则表达式(如我在这里的回答中所述)来搜索或解析输入,并使用字典获取相应的值。
Unum是一个做得很好并且文档详细的库。
优点:
缺点:
M
、S
等的变量)您还可以使用另一个库Magnitude。它支持您提到的所有SI单位前缀类型,而且它也会处理解析。引用自该网站:
物理量就是带有单位的数字,比如10 km/h。单位用字符串表示。它们可以是任何SI单位,以及一堆非SI单位、比特、美元和它们的任意组合。它们可以包括标准的SI前缀。
...
所有标准前缀都可以理解,从yocto到yotta,从kibi到exbi。
我不确定这是最好的答案,但在我的情况下它是有效的。欢迎验证我的解决方案。这是我第一次使用Python,欢迎提出建设性批评...以及积极的反馈 :D
以下是我的代码:
class Units:
def __init__(self):
global si;
si = {
-18 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-17 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-16 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-15 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-14 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-13 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-12 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-11 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-10 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-9 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-8 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-7 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-6 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-5 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-4 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-3 : {'multiplier' : 10 ** 3, 'prefix' : 'm'},
-2 : {'multiplier' : 10 ** 2, 'prefix' : 'c'},
-1 : {'multiplier' : 10 ** 1, 'prefix' : 'd'},
0 : {'multiplier' : 1, 'prefix' : ''},
1 : {'multiplier' : 10 ** 1, 'prefix' : 'da'},
2 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
3 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
4 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
5 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
6 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
7 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
8 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
9 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
10 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
11 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
12 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
13 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
14 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
15 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
16 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
17 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
18 : {'multiplier' : 10 ** 18, 'prefix' : 'E'},
}
def convert(self, number):
# Checking if its negative or positive
if number < 0:
negative = True;
else:
negative = False;
# if its negative converting to positive (math.log()....)
if negative:
number = number - (number*2);
# Taking the exponent
exponent = int(math.log10(number));
# Checking if it was negative converting it back to negative
if negative:
number = number - (number*2);
# If the exponent is smaler than 0 dividing the exponent with -1
if exponent < 0:
exponent = exponent-1;
return [number * si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent bigger than 0 just return it
elif exponent > 0:
return [number / si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent is 0 than return only the value
elif exponent == 0:
return [number, ''];
c1 = +1.189404E-010
fres = -4.07237500000000E+007;
ls = +1.943596E-005;
units = sci.Units();
rValue, rPrefix = units.convert(c1);
print rValue;
print rPrefix;
print units.convert(fres);
print units.convert(ls);
118.9404
p
[-40.72375, 'M']
[19.435959999999998, 'u']
我不知道是否有人会发现这个有用,但我希望你会。我在这里发布是为了让需要帮助的人看到,并给他们一个想法,也许他们可以优化它 :)
我知道这是一个旧的帖子,但我想提供一个参考,即我编写的一个Python库,可以处理各种前缀单位转换。
以下是主要功能列表:
kB
转换为GiB
)1024 Bytes == 1KiB
)<<
,>>
,&
,|
,^
)由于该问题尚未标记为已回答,我将在此提供我的解决方案,这在很大程度上受到si-prefix的启发,但我希望限制我的软件包依赖数量。
您可以使用以下函数:
def format_prefix(value, precision=2, unit="m"):
"""
Formats a numerical value with an appropriate SI prefix.
Args:
- value: A float representing the numerical value to be formatted.
- precision: An integer representing the number of decimal places to include in the formatted value (default: 2).
- unit: A string representing the unit of measurement to be appended to the formatted value (default: "m").
Returns:
- A string representing the formatted value with the appropriate SI prefix and unit.
Raises:
- ValueError: If the exponent is out of range of the available prefixes.
"""
SI_PREFIX_UNITS = u"yzafpnµm kMGTPEZY"
negative = False
digits = precision + 2
if value == 0.:
expof10 = 0
else:
if value < 0.:
value = -value
negative = True
expof10 = int(np.log10(value))
if expof10 > 0:
expof10 = (expof10 // 3) * 3
else:
expof10 = (-expof10 + 3) // 3 * (-3)
value *= 10 ** (-expof10)
if value >= 1000.:
value /= 1000.0
expof10 += 3
elif value >= 100.0:
digits -= 2
elif value >= 10.0:
digits -= 1
if negative:
value *= -1
expof10 = int(expof10)
prefix_levels = (len(SI_PREFIX_UNITS) - 1) // 2
si_level = expof10 // 3
if abs(si_level) > prefix_levels:
raise ValueError("Exponent out range of available prefixes.")
return f"{round(value*10**digits)/10**digits} "+SI_PREFIX_UNITS[si_level + prefix_levels].strip()+unit
>>> format_prefix(123687.2e-9, unit="m")
'123.69 µm'
>>> format_prefix(123687.2e-9, precision=12, unit="rad")
'123.6872 µrad'
@naitsirhc,感谢你的包。 我已经添加了一个小功能来使用你的包
import pandas as pd
import collections
Measure = collections.namedtuple('Measure', 'SLOT TEXT AVG HIGH LAST LOW SIGMA SWEEPS')
d=[Measure(SLOT='1', TEXT='CH1,AMPLITUDE', AVG='584.4782173493248E-3', HIGH='603.9744119119119E-3', LAST='594.125218968969E-3', LOW='561.1797735235235E-3', SIGMA='5.0385410346638E-3', SWEEPS='237996'), Measure(SLOT='2', TEXT='CH1,FREQUENCY', AVG='873.9706607717992E+6', HIGH='886.1564731675113E+6', LAST='873.9263571643770E+6', LOW='854.8833348698727E+6', SIGMA='4.382200567330E+6', SWEEPS='20705739'), Measure(SLOT='3', TEXT='CH4,PERIOD', AVG='1.1428492411436E-9', HIGH='1.1718844685593E-9', LAST='1.1432428766843E-9', LOW='1.1261916413092E-9', SIGMA='6.6735923746950E-12', SWEEPS='20680921'), Measure(SLOT='4', TEXT='CH4,FREQUENCY', AVG='875.0358282079155E+6', HIGH='887.9483414008331E+6', LAST='874.780693212961E+6', LOW='853.3264385945507E+6', SIGMA='5.0993358972092E+6', SWEEPS='20681008')]
from si_prefix import si_format
import si_prefix
si_prefix.SI_PREFIX_UNITS="yzafpnum kMGTPEZY"
def siSuffixNotation(element):
try:
ret=float(element)
return str(si_format(ret)).replace(' ','')
except ValueError:
return element
df=pd.DataFrame(d)
df.T.applymap(siSuffixNotation) #<= nice pretty print output table
0 1 2 3
SLOT 1.0 2.0 3.0 4.0
TEXT CH1,AMPLITUDE CH1,FREQUENCY CH4,PERIOD CH4,FREQUENCY
AVG 584.5m 874.0M 1.1n 875.1M
HIGH 604.0m 885.6M 1.2n 887.9M
LAST 586.5m 874.2M 1.1n 874.9M
LOW 561.2m 854.9M 1.1n 854.1M
SIGMA 5.0m 4.4M 6.7p 5.1M
SWEEPS 191.5k 16.7M 16.6M 16.6M
{'giga':1e9, 'kilo':1e3, 'milli':1e-3, ...}
)。 - Junuxx