Преобразование единиц в Python - PullRequest
11 голосов
/ 22 июня 2009

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

Однако я не могу внедрить это в свое приложение, если не смогу преобразовать градусы С (абсолютные) в К в градусы F в градусы R или любые их комбинации.

Я думал, может быть, что-то вроде этого будет работать:

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

Но ясно, что это неправильный путь. Какие-нибудь предложения для чистой реализации преобразований типа "смещение" в SymPy?

Примечание: я готов попробовать другие модули преобразования единиц, но не знаю ни одного, кроме Unum , и нашел его громоздким.

Редактировать: ОК, теперь ясно, что я хочу сначала определить, находятся ли две сравниваемые величины в одной и той же системе координат. (например, единицы времени относятся к разным эпохам или часовым поясам или дБ к прямой амплитуде), выполните соответствующее преобразование, затем выполните преобразование. Существуют ли общие инструменты управления системой координат? Это было бы прекрасно.

Я бы сделал предположение, что ° F и ° C всегда относятся к Δ ° F Δ ° C ​​в выражении, но относятся к абсолютному, когда стоят одни. Мне было просто интересно, есть ли способ сделать units.degF функцией и добавить к ней декоратор property(), чтобы справиться с этими двумя условиями.

Но сейчас я установлю units.C == units.K и попытаюсь четко указать в документации, как использовать функции convertCtoK(...) и convertFtoR(...) при работе с абсолютными единицами. (Шучу. Нет, не буду.)

Ответы [ 4 ]

8 голосов
/ 22 июня 2009

Документация Unum содержит довольно хорошую запись о том, почему это сложно:

Unum не может надежно обрабатывать преобразования между градусами Цельсия и Кельвина. Эта проблема называется «проблемой ложного происхождения»: 0 ° по Цельсию определяется как 273,15 К. Это действительно особый и раздражающий случай, поскольку в целом на значение 0 не влияет преобразование единиц измерения, например, 0 [м] = 0 [миль] = .... Здесь преобразование Кельвин / градус Цельсия характеризуется коэффициентом 1 и смещением 273,15 К. Смещение невозможно в текущей версии Unum.

Более того, он, вероятно, никогда не будет интегрирован в будущую версию, поскольку существует также концептуальная проблема: смещение следует применять, если величина представляет абсолютную температуру, но не следует, если количество представляет разницу температур. Например, повышение температуры на 1 ° по Цельсию эквивалентно повышению на 1 К. Невозможно угадать, что у пользователя на уме, является ли это абсолютной или относительной температурой. Вопрос об абсолютных и относительных количествах не важен для других единиц, поскольку ответ не влияет на правило преобразования. Unum не может провести различие между этими двумя случаями.

Концептуально довольно легко увидеть проблемы с попыткой символически представить абсолютное преобразование температуры. С любой нормальной относительной единицей (x unit) * 2 == (x * 2) unit - единая математика является коммутативной. При абсолютных температурах это нарушается - трудно сделать что-то более сложное, чем прямое преобразование температуры без других единиц измерения. Вероятно, лучше всего хранить все расчеты в Кельвинах и преобразовывать единицы измерения температуры в другие единицы только в точках входа и выхода вашего кода.

4 голосов
/ 22 июня 2009

Лично мне нравится Количества благодаря интеграции NumPy , однако он работает только с относительными температурами, а не с абсолютными.

0 голосов
/ 09 августа 2014

Пакет 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 голосов
/ 22 июня 2009

Пример того, как это может работать:

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