用于在SI单元前缀之间转换的Python库

时间:2012-06-10 15:03:21

标签: python

我正在寻找一个python库,它支持在各种SI前缀之间转换数字,例如,千克到微微,纳米到千兆等等。你会推荐什么?

5 个答案:

答案 0 :(得分:10)

我将一个简单的函数(original C version written by Jukka “Yucca” Korpela)移植到Python,以根据SI标准格式化数字。我经常使用它,例如,在图上设置刻度标签等。

您可以使用以下方式安装:

pip install si-prefix

来源可用on 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

答案 1 :(得分:5)

字典

如果您不想使用下面列出的任何第三方库,您实际上可以实现自己的解析功能。

使用字典将前缀与其值匹配。我已经为你做过了:

_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
    }

然后你可以使用正则表达式(如my answer here所述)来搜索或解析输入并使用字典来获取适当的值。


UNUM

Unum完成并完整记录了库。

优点:

  • 允许您定义任意单位(幅度仅支持用户定义的单位,只要它们是基本单位的组合)。

<强>缺点:

  • 不能很好地处理前缀
  • 将您的命名空间与其所有单元定义混淆(您最终会在命名空间中使用名为MS等的变量。

幅度

您还可以使用另一个库Magnitude。它支持您正在讨论的所有SI单元前缀,此外它还将处理解析。来自网站:

  

物理量是一个单位的数字,如10 km / h。单位指定为字符串。它们可以是任何SI单位,加上一堆非SI,位,美元以及它们的任意组合。 它们可以包含标准SI前缀。
  ...
  可以理解所有标准前缀,从yocto到yotta,从kibi到exbi。

答案 2 :(得分:4)

我不知道这是否是最好的答案,但它在我的情况下是有效的。随意验证我的解决方案。我是第一次使用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']

我不知道是否有人会发现这有用与否。我希望你会。我已经发布在这里,所以想要帮助的人也可以给他们一个想法,也许他们可以优化它:)

答案 3 :(得分:1)

我知道这是一个旧线程,但我想抛弃对我编写的python库的引用,该库处理所有方式的前缀单元转换处理

这是主要功能列表:

答案 4 :(得分:1)

QuantiPhy是一个新的包,可以转换为具有SI比例因子的数字。单位打包(例如Unum和Magnitude)通常是更好的选择,它们更重,并且专注于单位而不是比例因子。

QuantiPhy提供数量,这是一个将数字与其度量单位组合在一起的对象(单位是可选的)。创建数量时,您可以使用SI单位前缀。获得数量后,您可以在表达式中使用它,它可以充当浮点数。或者您可以将其转换为字符串,在这种情况下,它默认使用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

默认情况下,QuantiPhy在渲染到字符串时使用自然前缀,这可能是您想要的。但您可以使用缩放强制它呈现为特定前缀:

>>> 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

在这种情况下,您必须关闭SI单位前缀以避免获得多个前缀:'1 npg'。

更自然的例子可能是你转换单位的地方:

>>> l = Quantity('2um')                                                      
>>> print(l.render(scale='Å'))                                               
20 kÅ                                                                        

>>> print(f'{l:sÅ}')                                                         
20 kÅ

最后一个示例显示您可以在类型之后将所需单位放置在格式字符串中,并且将自动为您完成转换。