问题 Python中的单位转换


SymPy 是一个很好的工具,用于在Python中进行单位转换:

>>> from sympy.physics import units
>>> 12. * units.inch / units.m
0.304800000000000

你可以轻松自己动手:

>>> units.BTU = 1055.05585 * units.J
>>> units.BTU
1055.05585*m**2*kg/s**2

但是,我无法将此实现到我的应用程序中,除非我可以将度C(绝对值)转换为K度数到度数R或其任何组合。

我想也许这样的事情可行:

units.degC = <<somefunc of units.K>>

但显然这是走错路。在SymPy中干净地实现“偏移”型单位转换的任何建议?

注意:我愿意尝试其他单位转换模块,但除此之外不知道 UNUM,发现它很麻烦。

编辑:好的,现在很清楚,我想要做的是首先确定要比较的两个量是否在同一个坐标系中。 (如时间单位参考不同的时期或时区或dB到直线幅度),进行适当的变换,然后进行转换。有没有通用的坐标系管理工具?那太好了。

我会假设°F和°C总是指表达式中的Δ°FΔ°C,但是当单独站立时指的是绝对值。我只是想知道是否有办法制作 units.degF 一个函数和一个装饰器 property() 在它上面处理这两个条件。

但是现在,我会定的 units.C == units.K 并尝试在文档中非常清楚地使用函数 convertCtoK(...) 和 convertFtoR(...) 在处理绝对单位时。 (开个玩笑。不,我不会。)


11541
2018-06-22 00:41


起源

太糟糕了 sympy.physics.units 没有文件。 - Craig McQueen
GNU单元将它们分成 degF 和 tempF(x): gnu.org/software/units/manual/... - endolith


答案:


我个人喜欢 数量 感谢它 NumPy的 整合,但它只做相对温度,而不是绝对。


4
2018-06-22 01:07



我想你可能会让我卖掉数量。不错,轻巧,整齐,不确定/启动。谢谢。 ..仍然寻找一个体面的解决“偏移坐标系问题”。 - Paul
你会推荐它吗? 单位? - endolith


Unum文档有一个非常好的文章,说明为什么这很难:

Unum无法可靠地处理摄氏度和开尔文之间的转换。该问题被称为“错误原点问题”:0°C被定义为273.15 K.这实际上是一种特殊且烦人的情况,因为通常值0不受单位转换的影响,例如0 [m] = 0 [英里] = ....这里,转换开尔文/摄氏度的特征在于因子1和273.15K的偏移。在当前版本的Unum中偏移是不可行的。

此外,它可能永远不会被整合到未来版本中,因为还存在一个概念性问题:如果数量代表绝对温度,则应该应用偏移,但如果数量代表温度差异则不应该应用。例如,温度升高1摄氏度相当于升高1 K.无论是绝对温度还是相对温度,都无法猜测用户心中的含量。绝对与相对数量的问题对于其他单位而言并不重要,因为答案不会影响转换规则。 Unum无法区分这两种情况。

从概念上看,尝试用符号表示绝对温度转换很容易。对于任何正常的相对单位, (x unit) * 2 == (x * 2) unit - 单元数学是可交换的。在绝对温度下,它会发生故障 - 除了没有其他单位尺寸的直接温度转换之外,很难做更复杂的事情。您可能最好将所有计算保持为开尔文,并仅在代码的入口和出口处转换为其他温度单位。


8
2018-06-22 01:00



有一个原因是有datetime和timedelta对象。什么阻止对温度做同样的事情? - jfs
您可以这样做,您无法将绝对温度单位集成到符号数学库中,其中单位数学是可交换的。 - Miles
你可以很好地整合它。看到我的回答 stackoverflow.com/questions/1025145/units-conversion-in-python/... - jfs
对于任何未来的读者:请非常小心Unum。 Unum从很久以来就没有维护,它使用了一个名为的函数 as,这是python 2.6中的保留关键字。请考虑数量模块。 - Stefano Borini
这是一个相当薄弱的借口。 GNU单元可以处理两者 degC (亲戚)和 tempC (绝对)。它也可以处理分贝,其中涉及转换的对数。 - endolith


示例,它是如何工作的:

>>> T(0*F) + 10*C
T(265.37222222222221*K) # or T(47767/180*K)
>>> T(0*F + 10*C)
T(283.15*K)
>>> 0*F + T(10*C)
T(283.15*K)
>>> 0*F + 10*C
10*K
>>> T(0*F) + T(10*C)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'absolute_temperature' and \
'absolute_temperature'
>>> T(0*F) - T(10*C)
T(245.37222222222223*K) # or T(44167/180*K)
>>> 0*F - 10*C
-10*K

0
2018-06-22 02:04



>>> T(0 * F + 10 * C)#? - Miles
@Miles:感谢你的评论像答案一样神秘!从复制/粘贴中遗漏了一些东西。 T是物理学中的特斯拉。但我想我自己要重新定义它.. - Paul
@bpowah: T 是 absolute_temperature 这里。 - jfs
@Miles:0 * F,10 * C - 相应的华氏度和摄氏度的相对温度(非绝对值)。不是这样 physics.units,只是类似的语法。 - jfs
@ J.F。塞巴斯蒂安:我理解。我的评论是T(0 * F + 10 * C)== T(283.15 * K)没有任何意义,因为那就是说T(10 * K)== T(283.15 * K)。在T(10 * C)== T(283.15 * K)的情况下,难以得到10 * C == 10 * K. - Miles


NATU 包处理温度单位。例如,你可以这样做:

>>> from natu.units import K, degC, degF
>>> T = 25*degC
>>> T/K
298.1500
>>> T/degF
77.0000
>>> 0*degC + 100*K
100.0 degC

也支持前缀:

>>> from natu.units import mdegC
>>> 100*mdegC/K
273.2500

NATU 还处理非线性单位,如 分贝,而不仅仅是那些有抵消的人 摄氏度 和 华氏度

关于您给出的第一个示例,您可以这样做:

>>> from natu import units
>>> 12*units.inch/units.m
0.3048

BTU 已经内置。您可以将其显示单位更改为m ** 2 * kg / s ** 2,但默认情况下 NATU 将单元简化为J:

>>> from natu.units import BTU
>>> BTU.display = 'm2*kg/s2'
>>> 1*BTU
1055.05585262 J

0
2017-08-08 20:01