Python中的单位转换
Posted
技术标签:
【中文标题】Python中的单位转换【英文标题】:Unit Conversion in Python 【发布时间】:2011-01-08 15:58:15 【问题描述】:我正在开展一个项目,该项目允许用户随时间跟踪不同的数据类型。基本思想的一部分是用户应该能够使用他们需要的任何单位输入数据。我一直在研究这两个单位:
http://pypi.python.org/pypi/units/
和数量:
http://pypi.python.org/pypi/quantities/
但是我不确定最好的方法。据我所知,数量更复杂,但包含更好的初始单位列表。
【问题讨论】:
我认为您需要更具体地了解您的问题是什么,才能获得有效的答案。 我假设您将存储标准化为 SI 单位的数据,所以这实际上是输入的解析问题,并且可能是输出的转换问题。使用具有最佳解析/转换的库 - 您可以在进出的过程中使用不同的库。 不幸的是,python中有很多解决方案。 pint.readthedocs.org/en/latest/… 【参考方案1】:我赞成在科学计算应用程序中使用显式单位。使用明确的单位类似于刷牙。它预先增加了一些乏味,但从长远来看,您获得的类型安全可以节省很多麻烦。比如,not crashing $125 million orbiters into planets。
您还应该查看这两个其他 python 单位/数量包:
Unum
Scientific.Physics.PhysicalQuantity
我曾经研究过 Scientific.Physics.PhysicalQuantity。它不能完全满足我的需求,但可能会满足你的需求。从您的简短描述中很难判断您需要哪些功能。
我最终编写了自己的用于单位转换和维度分析的 python 包,但它尚未正确打包以供发布。我们在 Python 绑定中使用我的单位系统,用于我们的 OpenMM 系统,用于 GPU 加速分子力学。您可以在以下位置浏览我的 python 单元代码的 svn 存储库:
SimTK python units
最终我打算将其打包以进行分发。如果你觉得有趣,请告诉我。这可能会促使我尽快将其打包。我在设计 SimTK python 单位系统时一直在寻找的功能包括:
-
单位不一定在内部以 SI 单位存储。这对我来说非常重要,因为对我们来说一个重要的应用领域是分子尺度。在内部使用 SI 单位会导致常用分子力计算中的指数溢出。在内部,所有单位系统在 SimTK 中都同样重要。
我希望与 C++ 中的Boost.Units 系统具有相似的功能和灵活性。既因为我熟悉那个系统,也因为它是在一大群杰出工程师的监督下设计的。 Boost.Units 是一个精心设计的第二代维度分析系统。因此,我可能会争辩说 SimTK 单位系统是第三代系统:)。请注意,虽然 Boost.Units 是一个没有运行时成本的“零开销”系统,但所有 python 数量的实现,包括 SimTK 单元,都可能需要运行时成本。
我想要与 numpy 数组兼容的维度数量,但不一定需要 python numpy 包。换句话说,数量可以基于 numpy 数组或内置 python 类型。
哪些功能对您很重要?
【讨论】:
【参考方案2】:Pint 最近来到了这个领域。有人愿意分享他们的经验吗?看起来不错。仅供参考:在不久的将来它看起来像Pint will be integrated with Uncertainties。
【讨论】:
我在写这篇文章时正在评估 Pint,但一个很大的 +1 是它能够使用 Decimal 这意味着没有时髦的浮点舍入错误 - 所有提到的库都提到似乎只适用于浮点类型 - python-in-the-lab.blogspot.ca/2013/01/… 我不再像 Pint 那样大 +1 - 在过去的两天里,我已经提交了两个错误修复 - 我正在争论我是否真的需要额外的功能/复杂性,而是可以使用直截了当的东西,比如code.activestate.com/recipes/… @user90855 看看帖子的更新。该错误是开发分支中的一个回归,在它进入 master 之前已得到纠正。 Pint 实际上并不支持小数,不幸的是;在内部,常量表示为浮点数并从中转换为小数,这会导致不精确。【参考方案3】:注意quantities
对温度的支持很差:
>>> (100 * pq.degC).rescale(pq.degF)
array(179.99999999999997) * degF
>>> (0 * pq.degC).rescale(pq.degF)
array(0.0) * degF
0 摄氏度不是 0 华氏度。他们的框架不支持任何类型的转换,而不仅仅是乘以一个因子。
【讨论】:
温度很棘手,因为有两种类型 - 绝对/热力学温度和相对/温差。绝对,每个人都知道 0 °F != 0 °C。当谈到温差 (ΔT) 时,0 °F == 0 °C。 截至February 21st, 2020
,0°C
--> 0°F
行为仍然发生在quantities==0.12.4
。【参考方案4】:
还有一个来自 yt 项目的名为 unyt 的包。 unyt 的作者承认 Pint 和 astropy.units 的存在。支持与这些其他包之间的转换。
unyt 的卖点是速度。它比其他两个更快。在这个paper 中对单元包进行了多个基准测试。
对于那些痴迷于性能的人来说,基准测试是令人失望的。 :-( 使用这些单位系统中的任何一个的计算速度都会大大降低。对于具有 1000 个条目的数组,减速系数为 6-10(对于较小的数组更糟)。
免责声明:我不隶属于 unyt,我只是想分享我对单位系统的了解。
【讨论】:
【参考方案5】:我很惊讶没有人提到 SymPy。 SymPy 是一个成熟且维护良好的 Python 符号数学库,也是一个 NumFOCUS-sponsored 项目。
它有一个Physics 模块,其中包含许多有用的类和函数,用于“解决物理问题”。与您最相关的是,我认为它有一个 Unit 子模块,其中包含您需要的一切;只需阅读优秀的文档。
【讨论】:
【参考方案6】:看起来另一个包也可以做到这一点,由 web2py 成名的 Massimo DiPierro 编写,名为 Buckingham。
另外值得注意的是,Brian 这样的事情已经有一段时间了。
【讨论】:
白金汉似乎不完整,无法从克转换为磅,例如:>>> (Number(100, dims='gram')).convert('pound').value
导致RuntimeError: Incompatible Dimensions
丹尼尔,您提到的特定错误是因为磅的内部定义是力的单位而不是质量。此外,它当然没有详尽的受支持单位列表。
啊,这是有道理的,要添加磅质量支持,请将 'lb': (453.592,0,0,1,0,0,0), # lb
添加到 UNITS
列表中。【参考方案7】:
您可能想查看一个名为natu 的新包。它解决了@ChristopherBruns 列出的三个问题。它在PyPI 中可用。
我是该软件包的作者,如果有任何 cmets 或建议,我将不胜感激。
【讨论】:
【参考方案8】:我认为你应该使用数量,因为数量有一些与之相关的单位。
例如,压力是一个可以输入并转换为不同单位(Pa、psi、atm 等)的量。或许您可以为您的应用程序创建新的数量细节。
【讨论】:
【参考方案9】:想提一下 units 包,它是 Astropy 包的一部分。
它维护良好,易于使用,并且具有所有基本单位(以及与天体物理学相关的单位)。 它为单位和数量提供了工具。还有一个physical constants 的模块。
【讨论】:
【参考方案10】:我想指出一个用于处理单位的单独库: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 计量单位字典)更适合石油和天然气领域,但也应该可以在它之外使用。
【讨论】:
以上是关于Python中的单位转换的主要内容,如果未能解决你的问题,请参考以下文章
Python实现ParseDuration-支持解析字符串格式的时间单位,例如将小时或者分钟数转换为秒