52

我正在做一个项目,让用户随着时间的推移跟踪不同的数据类型。基本思想的一部分是用户应该能够使用他们需要的任何单位输入数据。我一直在看两个单位:

http://pypi.python.org/pypi/units/

和数量:

http://pypi.python.org/pypi/quantities/

但是我不确定最好的方法。据我所知,数量更复杂,但包含更好的初始单位列表。

4

11 回答 11

35

我赞赏在科学计算应用程序中使用显式单位。使用明确的单位类似于刷牙。它预先增加了一些乏味,但从长远来看,您获得的类型安全可以节省很多麻烦。比如说,不是将价值 1.25 亿美元的轨道飞行器撞向行星

您还应该查看这两个其他 python 单位/数量包:

乌姆

科学.物理.物理量

我曾经调查过 Scientific.Physics.PhysicalQuantity。它不能完全满足我的需求,但可能会满足你的需求。从简短的描述中很难说出您需要哪些功能。

我最终编写了我自己的用于单位转换和维度分析的 python 包,但它还没有正确打包以供发布。我们在 Python 绑定中使用我的单位系统,用于我们的 OpenMM 系统,用于 GPU 加速分子力学。您可以在以下位置浏览我的 python 单元代码的 svn 存储库:

SimTK python 单元

最终,我打算将其打包以进行分发。如果你觉得有趣,请告诉我。这可能会促使我尽快将其打包。我在设计 SimTK python 单位系统时一直在寻找的功能包括以下内容:

  1. 单位不一定在内部以 SI 单位存储。这对我来说非常重要,因为对我们来说一个重要的应用领域是分子尺度。在内部使用 SI 单位会导致常用分子力计算中的指数溢出。在内部,所有单位系统在 SimTK 中都同样重要。
  2. 我想要与C++中的Boost.Units系统类似的功能和灵活性。既因为我熟悉那个系统,也因为它是在一大群杰出工程师的监督下设计的。Boost.Units 是一个精心设计的第二代维度分析系统。因此,我可能会争辩说 SimTK 单位系统是第三代系统:)。请注意,虽然 Boost.Units 是一个没有运行时成本的“零开销”系统,但所有 python 数量实现,包括 SimTK 单元,可能都需要运行时成本。
  3. 我想要与 numpy 数组兼容的维度数量,但不一定需要 python numpy 包。换句话说,数量可以基于 numpy 数组或内置 python 类型。

哪些功能对您很重要?

于 2010-02-05T17:49:50.960 回答
25

品脱最近来到了这个领域。有人愿意分享他们的经验吗?看起来挺好的。仅供参考:看起来Pint 将在不久的将来与不确定性集成。

于 2013-06-11T00:06:16.893 回答
10

yt 项目中还有另一个名为unyt的包。unyt 的作者承认 Pint 和 astropy.units 的存在。支持与这些其他包之间的转换。

unyt 的卖点是速度。它比其他两个更快。本文在几个基准测试中对单元包进行了比较。

对于任何痴迷于性能的人来说,这些基准都是令人失望的。:-( 使用这些单位系统中的任何一个的计算速度都会大大降低。对于具有 1000 个条目的数组,减速系数为 6-10(对于较小的数组更糟)。

免责声明:我不隶属于 unyt,我只是想分享我对单位系统的了解。

于 2018-06-12T15:07:20.647 回答
9

请注意,quantities它对温度的支持非常糟糕:

>>> (100 * pq.degC).rescale(pq.degF)
array(179.99999999999997) * degF
>>> (0 * pq.degC).rescale(pq.degF)
array(0.0) * degF

0摄氏度不是0华氏度。他们的框架不支持任何类型的转换,而不仅仅是乘以一个因子。

于 2012-02-14T09:02:39.520 回答
7

我很惊讶没有人提到 SymPy。SymPy是一个成熟且维护良好的 Python 符号数学库,也是NumFOCUS 赞助的项目。

它有一个物理模块,其中包含许多有用的类和函数,用于“解决物理问题”。与您最相关的是,我认为它有一个Unit子模块,其中包含您需要的一切;只需阅读优秀的文档。

于 2017-05-30T16:34:09.407 回答
5

看起来另一个包也可以做到这一点,由 web2py 成名的 Massimo DiPierro 编写,称为Buckingham

另外值得注意的是,布赖恩有这样的事情已经有一段时间了。

于 2010-10-20T23:46:43.577 回答
5

您可能想查看一个名为natu的新包。它解决了@ChristopherBruns 列出的三个问题。它在PyPI中可用。

我是该软件包的作者,如果有任何意见或建议,我将不胜感激。

于 2014-08-08T19:06:07.400 回答
2

想提一下作为 Astropy 包一部分的单位包。

它维护良好,易于使用,并且具有所有基本单位(以及与天体物理学相关的单位)。它为单位和数量提供了工具。还有一个物理常数模块。

于 2020-02-12T08:34:41.297 回答
2

我想指出一个用于处理单位的单独库:Barril

https://github.com/ESSS/barril

文档位于:https ://barril.readthedocs.io/en/latest/

虽然它确实支持从计算中创建“随机”单位(例如 Pint、unum 等),但它更适合拥有一个单位数据库(该库默认具有该数据库 - 请参阅:https://barril.readthedocs .io/en/latest/units.html和实现:https://github.com/ESSS/barril/blob/master/src/barril/units/posc.py)然后您可以根据相关单位。

它支持的在这方面有很大不同的一件事是处理“无量纲”的单位转换 - 例如 m3/m3 (即:)volume per volume,然后转换为cm3/m3并保持维度。

即:品脱:

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> m = ureg.meter
>>> v = 1 \* (m\*3)/(m\*3)
>>> v
<Quantity(1.0, 'dimensionless')>

然后,在那之后(据我所知),如果知道它是 m3/m3,就不可能正确地进行额外的单位转换。

在巴里尔:

>>> from barril.units import Scalar
>>> a = Scalar(3, 'm3/m3')
>>> a.GetValue('cm3/m3')
3000000.0
>>> a.category
'volume per volume'
>>> a.unit
'm3/m3'

并且a.GetValue('m3')(具有无效值)的东西会给出一个错误,说明转换实际上是无效的。

单位数据库(最初基于 POSC 计量单位字典)更适合石油和天然气领域,但也应该可以在它之外使用。

于 2021-09-04T13:41:22.623 回答
1

我认为你应该使用数量,因为数量有一些与之相关的单位。

例如,压力是一个可以输入并转换为不同单位(Pa、psi、atm 等)的量。可能您可以为您的应用程序创建新的数量细节。

于 2010-01-24T15:20:56.423 回答
1

我发现单位包比想要的要多。不需要太多代码就可以开始构建自己的函数,这些函数引用了极少数的基本数字。此外,它会强制您进行尺寸分析以防止错误。

def FtoC(Tf):
    return (Tf-32)*5/9
def CtoF(Tc):
    return 9*Tc/5+32
def CtoK(Tc):
    return Tc+273.15
def INCHtoCM(Inch):
    return 2.54 * Inch
def CMtoINCH(cm):
    return cm / INCHtoCM(1)
def INCHtoMETER(inch):
    return .01*INCHtoCM(inch)
def FOOTtoMETER(foot):
    return INCHtoMETER(12*foot)
def METERtoINCH(Meter):
    return CMtoINCH(100 * Meter)
def METERtoFOOT(Meter):
    return METERtoINCH(Meter)/12
def M3toINCH3(M3):
    return (METERtoINCH(M3))**3
def INCH3toGALLON(Inch3):
    return Inch3 / 231
def M3toGALLON(M3):
    return INCH3toGALLON(M3toINCH3(M3))
def KG_M3toLB_GALLON(KGperM3):
    return KGtoLBM(KGperM3) / M3toGALLON(1)
def BARtoPASCAL(bar):
    return 100000 * bar
def KGtoLBM(kilogram):
    return kilogram * 2.20462262185
def LBMtoKG(lbm):
    return lbm/KGtoLBM(1)
def NEWTONtoLBF(newton):
    return newton * KGtoLBM(1) * METERtoFOOT(1) / STANDARD_GRAVITY_IMPERIAL()
def LBFtoNEWTON(lbf):
    return lbf * STANDARD_GRAVITY_IMPERIAL() * LBMtoKG(1) * FOOTtoMETER(1)
def STANDARD_GRAVITY_IMPERIAL():
    return 32.174049
def STANDARD_GRAVITY_SI():
    return 9.80665
def PASCALtoPSI(pascal):
    return pascal * NEWTONtoLBF(1) / METERtoINCH(1)**2
def PSItoPASCAL(psi):
    return psi * LBFtoNEWTON(1) / INCHtoMETER(1)**2

然后假设您想绘制 1,3 丁二烯 @44 F 的静压头并使用 PSI 中的仪表,因为您住在美国,但密度表应该是 SI 单位...... ......

# butadiene temperature in Fahrenheit
Tf = 44

# DIPPR105 Equation Parameters (Density in kg/m3, T in K)
# valid in temperature 165 to 424 Kelvin
A=66.9883
B=0.272506
C=425.17
D=0.288139

# array of pressures in psi
Pscale = np.arange(0,5,.1, dtype=float)
Tk = CtoK(FtoC(44))
Density = A / (B**(1+(1-Tk/C)**D)) # KG/M3
Height = [PSItoPASCAL(P) / (Density * STANDARD_GRAVITY_SI()) for P in Pscale]
Height_inch =  METERtoINCH(1) * np.array(Height, dtype=np.single)
于 2022-02-06T21:51:40.387 回答