Единицы измерения физических величин в программах на языке Python
Введение
Язык Python (правильно это читается "Пайтон", но в русскоязычном сообществе так же прижилось и прочтение "Питон", мне оно тоже больше по душе ;) в последнее время получил очень большую популярность в среде непрограммистов по двум причинам:
лёгкий синтаксис, очень близкий к естественным языкам и математическому мышлению;
огромное количество различных библиотек (модулей), написанных как на самом питоне, так и на более быстрых "профессиональных" языках С/С++ и Фортран.
Хотя для изучения основ Питона есть очень много хорошей литературы, в том числе и на русском языке, вопросы использования многих модулей описаны недостаточно. Особенно тяжело здесь русскоязычным инженерам. Этой статьёй я хочу начать цикл туториалов, в которых я поделюсь своим опытом использования языка Питон в практической инженерной деятельности. В настоящем туториале речь пойдёт о модуле Pint, который сильно упрощает манипулирование физическими величинами.
Настоящие туториалы нельзя рассматривать как основы языка Питон. Предполагается, что читатель с ними знаком, а так же знаком с модулями Math, CMath, Numpy, Scipy, Pandas. Язык Питон и перечисленные модули хорошо описаны в литературе и Интернете.
Для начала немного теории, что бы освежить мозг
В инженерных расчётах очень большое значение имеет приведение, преобразование и отображение единиц измерения. Результат любых инженерных измерений и расчётов не имеет никакого смысла, если не указаны две его основные характеристики: единица измерения и точность. О точности я напишу следующий туториал, а сейчас поговорим об единицах измерения.
Напомню основные определения:
Физической величиной называется физическое свойство материального объекта, процесса, физического явления, охарактеризованное количественно.
Значение физической величины выражается одним или несколькими числами, характеризующими эту физическую величину, с указанием единицы измерения.
Размером физической величины являются значения чисел, фигурирующих в значении физической величины.
Единицей измерения физической величины является величина фиксированного размера, которой присвоено числовое значение, равное единице. Применяется для количественного выражения однородных с ней физических величин.
Размерность физической величины — выражение, показывающее связь этой величины с основными величинами данной системы физических величин; записывается в виде произведения степеней сомножителей, соответствующих основным величинам, в котором численные коэффициенты опущены.
Системой единиц физических величин называют совокупность основных и производных единиц, основанную на некоторой системе величин. Широкое распространение получило всего лишь некоторое количество систем единиц. В большинстве случаев во многих странах пользуются метрической системой.
Измерить физическую величину – значит сравнить ее с другой такой же физической величиной, принятой за единицу. Например, длину предмета сравнивают с единицей длины, массу тела – с единицей веса и т.д. Но если один исследователь измерит длину в саженях, а другой в футах, им будет трудно сравнить эти две величины. Поэтому все физические величины во всем мире принято измерять в одних и тех же единицах. В 1963 году была принята Международная система единиц СИ (System international - SI). Для каждой физической величины в системе единиц должна быть предусмотрена соответствующая единица измерения. Эталоном единицы измерения является ее физическая реализация. Эталоном длины является метр – расстояние между двумя штрихами, нанесенными на стержне особой формы, изготовленном из сплава платины и иридия. Эталоном времени служит продолжительность какого-либо правильно повторяющегося процесса, в качестве которого выбрано движение Земли вокруг Солнца: один оборот Земля совершает за год. Но за единицу времени принимают не год, а секунду. Единицы измерения, для которых существуют физические эталоны, называют основными единицами
Производными единицами измерения физических величин называют такие единицы, для которых нет физических эталонов и которые определяются через соотношения основных единиц. Например, за единицу скорости принимают скорость такого равномерного прямолинейного движения, при котором тело за 1 с совершает перемещение в 1 м - поэтому единица скорости обозначается . Единицей площади является площадь квадрата, длина каждой стороны которого равна 1 м - поэтому единица площади называется "квадратный метр" и обозначается .
Приставки используются для того, что бы сделать запись значения физической величины более компактным. Например, . приставки бывают десятичные и двоичные. Десятичные приставки представляют собой множители . Двоичные приставки представляют собой множители .
Основные единицы системы СИ
Величина |
Наименование |
Обозначение |
---|---|---|
Длина |
метр |
m |
Масса |
килограмм |
kg |
Время |
секунда |
s |
Сила электрического тока |
ампер |
A |
Термодинамическая температура |
кельвин |
K |
Сила света |
канделла |
cd |
Количество веществ |
моль |
mol |
Плоский угол |
радиан |
rad |
Телесный угол |
стерадиан |
sr |
Производные единицы системы СИ
Величина |
Наименование |
Обозначение |
Выражение через основные единицы |
Выражение через производные единицы |
---|---|---|---|---|
Частота |
герц |
Hz |
1\s |
- |
Сила |
ньютон |
N |
- |
|
Давление |
паскаль |
Pa |
||
Энергия, работа, количество теплоты |
джоуль |
J |
||
Мощность, поток энергии |
ватт |
W |
||
Количество электричества, заряд |
кулон |
С |
- |
|
Электрическое напряжение, потенциал |
вольт |
V |
||
Электрическая ёмкость |
фарада |
F |
||
Электрическое сопротивление |
ом |
Ω |
||
Электропроводность |
сименс |
S |
или |
|
Поток магнитной индукции |
вебер |
Wb |
||
Магнитная индукция |
тесла |
Т |
||
Индуктивность |
генри |
H |
||
Световой поток |
люмен |
Im |
- |
|
Освещённость |
люкс |
Ix |
- |
Физические и технические константы
Для удобства и наглядности работы, в том числе для перевода несистемных единиц в системные, кроме приставок и обозначения физических единиц, в модуле Pint определены некоторые физические константы:
Наименование |
Значение |
Обозначение |
---|---|---|
3.1415926535 |
pi |
|
Экспонента |
2.718281884 |
e |
Скорость света |
c speed_of_light |
|
Гравитационная постоянная |
g_0 graviti |
|
Вакуумная проницаемость |
mu_0 magnetic_constant |
|
Диэлектрическая проницаемость |
electric_constant |
|
Вакуумный импеданс |
Z_0 impedance_of_free_space characteristic_impedance_of_vacuum |
|
Постоянная Планка |
h |
|
Постоянная Дирака |
hbar |
|
Гравитационная константа Ньютона |
newtonian_constant_of_gravitation |
|
Молярная газовая постоянная |
R |
|
Число Авогадро |
N_A |
|
Постоянная Больцмана |
k |
|
Постоянная Вина |
wien_frequency_displacement_law_constant |
|
Постоянная Ридберга |
rydberg_constant |
|
Масса электрона |
m_e electron_mass |
|
Масса нейтрона |
m_n neutron_mass |
|
Масса протона |
m_p proton_mass |
Несистемные единицы
Модуль Pint содержит единицы не только системы СИ, но и других известных систем единиц, что позволяет применять его для перевода значений физических величин из одной системы единиц в другую. В модуле определено очень много разных единиц, поэтому не будем раздувать туториал ещё одной таблицей, вместо этого ниже будет показано, как получить названия нужных единиц средствами самого питона.
Десятичные приставки
Множитель |
Название |
Обозначение |
---|---|---|
иокто |
y |
|
зепто |
z |
|
aттo |
a |
|
фемто |
f |
|
пико |
p |
|
нано |
n |
|
микро |
μ |
|
милли |
m |
|
санти |
c |
|
деци |
d |
|
дека |
deka |
|
гекта |
h |
|
$10^3 |
кило |
k |
мега |
M |
|
гига |
G |
|
$10^{12} |
тера |
T |
$10^{15} |
пента |
P |
$10^{18} |
экса |
E |
$10^{21} |
зетта |
Z |
$10^{24} |
иотта |
Y |
Двоичные приставки
Множитель |
Название |
Обозначение |
---|---|---|
киби |
Ki |
|
меби |
Mi |
|
гиби |
Gi |
|
теби |
Ti |
|
пеби |
Pi |
|
эксби |
Ei |
|
зеби |
Zi |
|
иоби |
Yi |
Дополнительные приставки
Кроме стандартных приставок системы СИ, в модуле Pint определены три дополнительные приставки:
Множитель |
Обозначение |
---|---|
0.1 |
demi |
0.5 |
semi |
1.5 |
sesqui |
Установка и начало использования модуля Pint
Установка модуля производится стандартным для Python образом:
c:\>pip install pint
Если вы используете менеджер Anaconda, то команда установки будет такой:
c:\>conda install pint --channels conda-forge
Для использования модуля его надо импортировать в вашу программу. Рекомендуется это делать следующими командами:
>>>from pint import UnitRegistry
>>>ureg = UnitRegistry()
Вторая строка инициализирует объект класса UnitRegistry
, который хранит определения единиц измерения, их связи и обрабатывает преобразования между единицами (разумеется, имя объекта может быть произвольным, совсем не обязательно ureg
; можно даже определить несколько таких объектов, хотя я не могу представить, для чего это может быть нужно). При этом объект ureg
заполняется списком единиц и префиксов по умолчанию, полный список которых можно посмотреть в файле default_en.txt, который находится в папке, в которую установлена библиотека. Узнать расположение этой паки можно командой:
c:\>pip show pint
Name: Pint
Version: 0.19.2
Summary: Physical quantities module
Home-page: https://github.com/hgrecco/pint
Author: Hernan E. Grecco
Author-email: hernan.grecco@gmail.com
License: BSD
Location: c:\users\andre\anaconda3\lib\site-packages
Requires:
Required-by:
Другой способ увидеть, какие несистемные единицы уже определены в модуле. Для этого надо вызвать метод get_compatible_units()
объекта класса UnitRegistry
, передав ему величину интересующих единиц (в даном примере мы получаем возможные единицы измерения энергии):
>>>ureg.get_compatible_units('[energy]')
frozenset({<Unit('electron_volt')>,
<Unit('rydberg')>,
<Unit('hartree')>,
<Unit('erg')>,
<Unit('joule')>,
<Unit('foot_pound')>,
<Unit('calorie')>,
<Unit('fifteen_degree_calorie')>,
<Unit('international_calorie')>,
<Unit('atmosphere_liter')>,
<Unit('thermochemical_british_thermal_unit')>,
<Unit('international_british_thermal_unit')>,
<Unit('british_thermal_unit')>,
<Unit('watt_hour')>,
<Unit('US_therm')>,
<Unit('therm')>,
<Unit('ton_TNT')>,
<Unit('tonne_of_oil_equivalent')>,
<Unit('quadrillion_Btu')>})
Проверка того, определена ли единица измерения
Для того, что бы проверить, определена ли необходимая единица измерения, можно воспользоваться следующими командами Питона:
>>> 'MHz' in ureg
True
>>> 'gigatrees' in ureg
False
Дополнение списка единиц
Если требуемой единицы измерения в файле default_en.txt нет, её можно добавить тремя способами:
1. Дописать определение единицы в конец файла default_en.txt.
2. Создать свой собственный файл определения единиц, например, mydef.txt.
3. Добавить описание единицы программно.
Формат файла описания
Независимо от того, дописывается ли единица в файл default_en.txt или создаётся новый файл описания единиц, структура описания каждой единицы следующая:
hour = 60 * minute = h = hr
minute = 60 * second = min
Это довольно просто, не так ли? Мы говорим, что минута равна 60 секундам и также известна как "мин".
Первое слово – это всегда каноническое имя.
После знака равенства следует определение единицы, основанное на других, ранее определённых единицах.
После следующего знака равенства, опционально, указывается символ единицы измерения.
Наконец, опять же опционально, приводится список псевдонимов единицы измерения, разделенных знаками равенства. Если надо указать только псевдонимы без символа единицы, символ единицы должен быть заменён на символ "_":
millennium = 1e3 * year = _ = millennia
Эта команда определяет единицу "millennium", равную 1000 годам ("year", определена в файле default_en.txt) без символа единицы измерения. Так же определён псевдоним "millennia", который может использоваться в программе вместо обозначения "millennium".
Порядок определения единиц измерения не имеет значения, Pint разрешит зависимости, чтобы определить их в правильном порядке. Важно только, что бы все единицы, использованные справа от первого знака равенства, были определены в доступных файлах определения единиц. Если надо добавить единицу, которую нельзя выразить через другие определённые единицы, её следует выражать через эталонные физические размерности:
second = [time] = s = sec
time - это физическая величина
second - единица измерения времени (секунда)
Новые физические величины так же можно определять через другие физические величины:
[density] = [mass] / [volume]
Обратите внимание, что первичные физические величины не нужно объявлять.
Кроме основных единиц измерения, в файле описания определяются их кратные десятичные префиксы, они обозначаются конечным тире:
yocto- = 10.0**-24 = y-
Наконец, можно добавить псевдонимы к уже существующему определению единицы:
@alias meter = metro = metr
Кроме того, файл описания может содержать необрабатываемый библиотекой Pint комментарии, начинающиеся с символа "#" (как в синтаксисе Питона)
Создание собственного файла описания
Если вы добавляете новые описания в файл default_en.txt, то они могут пропасть при обновлении версии библиотеки - при этом будет установлен новый стандартный файл default_en.txt без добавленных вами определений. Что бы этого избежать, лучше собственные определения поместить в отдельный текстовой файл с произвольным именем, например, mydef.txt и загружать его в своих программах после импорта библиотеки и создания объекта класса UnitRegistry()
с помощью команды:
>>>ureg.load_definitions('/your_path/mydef.txt')
При этом ваши определения добавятся к стандартным. Если же вы ходите получить только свои определения и не загружать стандартные (например, если вы переопределяете стандартную единицу измерения), то передайте свой файл конструктору объекта:
>>>ureg = UnitRegistry('/your_path/mydef.txt')`
Добавление определения единицы измерения непосредственно в программе
Вы можете легко добавлять единицы измерения, измерения или псевдонимы в реестр программным путем. Давайте добавим dog_year
(иногда пишется как dy
), эквивалентный 52 (человеческим) дням:
>>>from pint import UnitRegistry
>>>ureg = UnitRegistry()
>>>Q_ = ureg.Quantity
>>>#Здесь мы добавляем новую единицу
>>>ureg.define('dog_year = 52 * day = dy')
>>>#Далее создаём количественную переменную и переводим её в новые единицы
>>>lassie_lifespan = Q_(10, 'year')
>>>print(lassie_lifespan.to('dog_years'))
В результате получим: 70.24038461538461 dog_year
. Обратите внимание, что мы использовали имя dog_years
хотя мы не определили форму множественного числа как псевдоним. Модуль Pint заботится об этом, поэтому вам не нужно этого делать. Формы множественного числа, которые не просто строятся путем добавления суффикса "s" к форме единственного числа, должны быть явно указаны как псевдонимы (см., например, millennia)
Вот, что тут любопытно: если вместо формы множественного числа
>>>print(lassie_lifespan.to('dog_years'))
написать в единственном числе:
>>>print(lassie_lifespan.to('dog_year'))
результат будет тот же самый. Зачем это сделано? Не знаю... Вероятно, что бы следовать принципам Питона в стремлении к максимальному приближению к естественному языку.
Вы также можете добавить префиксы программным путем:
>>>ureg.define('myprefix- = 30 = my-')
где число указывает на коэффициент умножения.
То же самое для псевдонимов и производных размеров:
>>>ureg.define('@alias meter = metro = metr')
>>>ureg.define('[hypervolume] = [length] ** 4')
Некоторые единицы содержат константы. Они могут быть определены с помощью ведущего подчеркивания:
>>>ureg.define('_100km = 100 * kilometer')
>>>ureg.define('mpg = 1 * mile / gallon')
>>>fuel_ec_europe = 5 * ureg.L / ureg._100km
>>>fuel_ec_us = (1 / fuel_ec_europe).to(ureg.mpg)
ПРЕДУПРЕЖДЕНИЕ
Единицы измерения, префиксы и псевдонимы, добавленные программным путем, забываются при завершении работы программы.
Присоединение единиц измерения к числам и переменным и вычисления с ними
Пожалуй, это самое главное назначение модуля Pint. Он позволяет присоединять единицы измерения к операндам вычислений и автоматически получать единицу результата. Для присоединения единиц измерения к операнду математической операции, надо всего лишь умножить операнд на объект ureg
:
>>>10 * ureg.kg + 20 * ureg.kg
30 <Unit('kilogram')>
В данном примере мы сложили 10 килограммов и 20 килограммов и получили 30 килограммов. Т.е. Питон сработал чисто математически - он вынес ureg.kg
за скобки и сложил 10 + 20. Но модуль Pint позволяет правильно прибавлять и граммы к килограммам:
>>>10 * ureg.kg + 300 * ureg.g
10.3 <Unit('kilogram')>
Если присвоить единицу измерения переменной, то она изменит свой тип на объект класса Quantity()
:
>>>distance = 24.0 # пока без единицы измерения
>>>type(distance)
float
>>>distance = distance * ureg.km # теперь distance равно 24 километра
>>>type(distance)
pint.quantity.build_quantity_class.<locals>.Quantity
Теперь обычная математика с переменной distance
невозможна:
>>>distance + 3
DimensionalityError: Cannot convert from 'kilometer' to 'dimensionless'
Так же нельзя и прибавить несовместимую единицу:
>>>distance + 3 * ureg.g
DimensionalityError: Cannot convert from 'kilometer' ([length]) to 'gram' ([mass])
Разумно - сложение расстояния и массы не имеет физического смысла. А вот умножать, делить и возводить в степени переменные с разными единицами можно:
>>>distance = 24.0 * ureg.km # расстояние 24 км
>>>time = 3.0 * ureg.hour + 30.0 * ureg.minute # время 3 часа 30 минут
>>>speed = distance / time # скорость это действительно пройденное расстояние, делённое на затраченное время
>>>print(speed)
7.199999999999999 kilometer / hour # поэтому иы и получили километры в час
>>>acceleration = distance / time ** 2
>>>print(acceleration)
2.1599999999999997 kilometer / hour ** 2
Мы можем посмотреть, какую размерность у нас имеют результаты вычислений:
>>>print(speed.dimensionality)
[length] / [time]
>>>print(acceleration.dimensionality)
[length] / [time] ** 2
При вычислении ускорения получилось вроде и правильно, но как то непривычно видеть . Можно преобразовать к более каноничным :
>>>print(acceleration.to('m/s**2'))
0.00016666666666666663 meter / second ** 2
В последнем примере интересно не только простота преобразования единиц измерения (метод to()
объектов класса Quantity()
), но и новый способ представления единиц измерения - в виде строки. Этот способ работает не только при преобразовании величин, но и во всех других случаях применения модуля Pint. Например:
>>>distance = 24.0 * ureg('km')
>>>print(distance)
24.0 kilometer
Вообще оба способа представления единиц измерения взаимозаменяемы во всех случаях и могут как угодно комбинироваться в одном выражении. Например, видоизменим команду преобразования единицы:
>>>print(distance.to(ureg.m))
24000.0 meter
Объекты Quantity()
также хорошо работают с массивами NumPy (соответственно, переменными с присоединенными единицами измерения можно использовать все функции математических модулей Numpy и Scipy) и таблицами Pandas
Выделение значения и единицы измерения
Как было выше сказано, после присоединения к переменной единицы измерения, переменная превращается в объект класса Quantity()
и дальнейшая математика с ней возможна только с другими объектами класса Quantity()
(величинами или переменными, имеющими совместимые единицы измерения). Строго говоря, это не совсем так. При необходимости из переменной (объекта) класса Quantity()
можно выделить её значение в обычную переменную типа int
или float
. Это возможно благодаря тому, что у всех объектов класса Quantity()
есть два свойства: magnetude
и units
- содержащие. соответственно, значение и единицу измерения:
>>>type(distance)
pint.quantity.build_quantity_class.<locals>.Quantity
>>>d = distance.magnitude
>>>type(d)
float
>>>print(distance.magnetude)
24.0
>>>print(distance.units)
kilometer
Упрощение единиц измерения
Иногда величина величины будет очень большой или очень маленькой. Метод to_compact()
может корректировать единицы измерения, чтобы сделать количество более удобочитаемым для человека:
>>>wavelength = 1550 * ureg.nm # длина волны 1550 нанометров
>>>frequency = (ureg.speed_of_light / wavelength).to('Hz') # разделим скорость света на длину волны и приведём результат к герцам
>>>print(frequency)
193414489032258.03 hertz
>>>print(frequency.to_compact())
193.41448903225802 terahertz
193 терагерца воспринимается человеком более естественно и понятно, чем 193414489032258 герц
Существуют также методы to_base_units()
и ito_base_units()
, которые автоматически преобразуют несистемные единицы в эталонные единицы СИ правильной размерности:
>>>height = 5.0 * ureg.foot + 9.0 * ureg.inch
>>>print(height)
5.75 foot
>>>print(height.to_base_units())
1.7525999999999997 meter
>>>print(height)
5.75 foot
>>>height.ito_base_units()
>>>print(height)
1.7525999999999997 meter
Из примера видно, что разница между этими методами в том. что метод to_base_units()
возвращет результат преобразования, а метод ito_base_units()
изменяет саму переменную.
Модуль Pint может автоматически приводить результаты вычислений к эталонным единицам СИ. Для этого при создании объекта класса UnitRegistry
надо передать конструктору параметр autoconvert_offset_to_baseunit = True
.
Существуют также методы to_reduced_units()
и ito_reduced_units()
, которые выполняют упрощенное уменьшение размеров, объединяя единицы измерения с одинаковой размерностью и не затрагивая остальные единицы измерения:
>>>density = 1.4 * ureg.gram / ureg.cm ** 3
>>>volume = 10 * ureg.cc
>>>mass = density * volume
>>>print(mass)
14.0 cubic_centimeter * gram / centimeter ** 3
>>>print(mass.to_reduced_units())
>>>print(mass)
14.0 cubic_centimeter * gram / centimeter ** 3
>>>mass.ito_reduced_units()
>>>print(mass)
14.0 gram
Конечно, измерять массу в кубических сантиметрах и граммах неправильно. Учитывая, что , метод сокращает эти единицы и остаются правильные граммы.
Модуль Pint может автоматически сокращать единицы и упрощать результат. Для этого при создании объекта класса UnitRegistry
надо передать конструктору параметр auto_reduce_dimensions = True
.
Синтаксический анализ строк
Как уже было показано выше, ещиницы измерения объекту ureg
можно передавать в виде строк. При этом содержимое строки может быть в достаточной степени произвольным. Всё дело в том. что модуль Pint содержит в себе мощный синтаксический анализатор строковых выражений. И его возможности не ограничиваются одним присоединением и преобразованием единиц измерения. Числа также анализируются, поэтому вы можете использовать выражение:
>>>ureg('2.54 * centimeter')
2.54 <Unit('centimeter')>
Можно так же использовать конструктор объекта класса Quantity
:
>>>Q_ = ureg.Quantity
>>>Q_('2.54 * centimeter')
2.54 <Unit('centimeter')>
Более того, знак "*" можно опускать:
>>>Q_('2.54cm')
2.54 <Unit('centimeter')>
Это позволяет вам написать простой конвертер единиц измерения:
>>>user_input = '2.54 * centimeter to inch'
>>>src, dst = user_input.split(' to ')
>>>Q_(src).to(dst)
1.0 <Unit('inch')>
Строки, содержащие значения, могут быть проанализированы более глубоко с помощью метода parse_pattern()
. В качестве шаблона используется строка, подобная формату, с определенными в ней единицами измерения:
>>>input_string = '10 feet 10 inches'
>>>pattern = '{feet} feet {inch} inches'
>>>ureg.parse_pattern(input_string, pattern)
[10.0 <Unit('foot')>, 10.0 <Unit('inch')>]
Чтобы выполнить поиск нескольких совпадений, установите параметр many = True
. Следующий пример демонстрирует, как анализатор может находить совпадения среди символов-заполнителей:
>>>input_string = '10 feet - 20 feet ! 30 feet.'
>>>pattern = '{feet} feet'
>>>ureg.parse_pattern(input_string, pattern, many=True)
[[10.0 <Unit('foot')>], [20.0 <Unit('foot')>], [30.0 <Unit('foot')>]]
Обратите внимание, что фигурные скобки ({}
) преобразуются синтаксическим анализатором в шаблон сопоставления с плавающей точкой.
Эта функция полезна для таких задач, как массовое извлечение единиц измерения из тысяч однородных строк или даже очень больших текстов, в которых единицы измерения разбросаны без определенного шаблона.
Форматирование строк
Физические величины можно легко распечатать несколькими способами.
Стандартный код форматирования строки
>>>accel = 1.3 * ureg['meter/second**2']
>>>print('The str is {!s}'.format(accel))
print('The str is {!s}'.format(accel))
Стандартный код форматирования представления
>>>print('The repr is {!r}'.format(accel))
print('The repr is {!r}'.format(accel))
Доступ к полезным атрибутам
>>>print('The magnitude is {0.magnitude} with units {0.units}'.format(accel))
The magnitude is 1.3 with units meter / second ** 2
Модуль Pint также поддерживает форматирование с плавающей запятой для массивов Numpy:
>>>import numpy as np
>>>accel = np.array([-1.1, 1e-6, 1.2505, 1.3]) * ureg['meter/second**2']
>>>print('The array is {:.2f}'.format(accel))
The array is [-1.10 0.00 1.25 1.30] meter / second ** 2
>>>print('The array is {:+.2E~P}'.format(accel))
The array is [-1.10E+00 +1.00E-06 +1.25E+00 +1.30E+00] m/s²
Модуль Pint поддерживает f-строки Питона:
>>>accel = 1.3 * ureg['meter/second**2']
>>>print(f'The str is {accel}')
he str is 1.3 meter / second ** 2
>>>print(f'The str is {accel:.3e}')
The str is 1.300e+00 meter / second ** 2
>>>print(f'The str is {accel:~}')
The str is 1.3 m / s ** 2
>>>print(f'The str is {accel:~.3e}')
The str is 1.300e+00 m / s ** 2
Так же можно выводить строки в форматах HTML и LaTeX:
>>>accel = 1.3 * ureg['meter/second**2']
>>>print('The pretty representation is {:P}'.format(accel))
The pretty representation is 1.3 meter/second²
>>>print('The HTML representation is {:H}'.format(accel))
The HTML representation is 1.3 meter/second<sup>2</sup>
>>>print('The LaTeX representation is {:L}'.format(accel))
The LaTeX representation is 1.3\ \frac{\mathrm{meter}}{\mathrm{second}^{2}}
Если вы хотите использовать сокращенные названия единиц измерения, добавьте перед спецификацией префикс ~.
Спецификации форматирования (L, H и P) можно использовать с синтаксисом форматирования строк с плавающей точкой. Например, научная нотация:
>>>print('Scientific notation: {:.3e~L}'.format(accel))
Scientific notation: 1.300\\times 10^{0}\\ \\frac{\\mathrm{m}}{\\mathrm{s}^{2}}
Кроме того, вы можете указать спецификацию формата по умолчанию:
>>>ureg.default_format = 'P'
>>>print('The acceleration is {}'.format(accel))
The acceleration is 1.3 meter/second²
Комментарии (42)
buratino
13.08.2022 10:33+2цикл туториалов,
вызывает непреодолимое желание воспитать ссаными тряпками
MAK74 Автор
13.08.2022 12:45-1Ну воспитывай ;)
buratino
13.08.2022 16:02+3Если заявлено про материалы на русском языке и русскоязычные инженеры, то надо писать хотя бы в названии на русском языке, а не на не пойми каком
Megakazbek
13.08.2022 16:26Я так понимаю, что "материалы" и "инженеры" - это исконно русские слова?
Javian
13.08.2022 16:34+3"Туториал" отсутствует в словаре иностранных слов русского языка.
Megakazbek
13.08.2022 23:17Словарь - это археология языка, там написано то, каким язык когда-то был, и то в меру кругозора его составителей. Мало того, что абсолютно все слова языка невозможно выявить даже очень целеустремлённой группе авторов и часть слов в словарь так и не попадает, так к тому же в первую же секунду после публикации он начинает устаревать. А то, какой язык есть сейчас, можно понять только по тем словам, которые люди прямо сейчас используют, так как именно это определяет язык, а не словарь.
vadimr
13.08.2022 11:18В качестве курсовой работы это нормально, но в реальной практике физические расчёты опираются на библиотеки вычислительных алгоритмов, которые ни о каких единицах измерения не имеют понятия, а зачастую и прямо нарушают их систему некоторыми численными приближениями.
MAK74 Автор
13.08.2022 12:45Как минимум после применения любых библиотек, надо добавить единицу измерения результата - иначе непонятно, слонов ты получил или паровозы. Но что бы не ошибиться, не запутаться и не делать кучу ручной работы, лучше единицы добавить в самом начале расчётов - фишка модуля pint именно в том, что дальше вы можете применять любые библиотеки вычислительных алгоритмов, при этом и единицы измерения будут правильно преобразовываться, а в случае если вычислительный алгоритм будет применен неверно с точки зрения обсчитываемого физического процесса - т.е. в результате вычисления вылезет несовместимая или несуществующая единица измерения, - то сразу получим исключение, не усугубляя дальше неправильный расчёт
vadimr
13.08.2022 13:21Половина численных методов основана на приближенных равенствах вроде x ≈ x**2 при x ≈ 1 и т.п. Естественно, единицы измерения при этом не сохраняются, и это не является признаком неправильного расчёта.
Эти все фишки с единицами измерения дальше школьной арифметики не работают. Уже банальное разложение в ряд Тейлора - фундамент матанализа - не сохраняет единицы измерения в обыденном понимании (которое лежит в основе описываемой библиотеки). Надо было бы придумывать предельный переход бесконечной последовательности единиц измерения и т.п. А ряд Тейлора - это только один простой частный случай.
MAK74 Автор
13.08.2022 13:46Для расчётов с неопределённостями в Питоне тоже есть специальный модуль (и я как раз сейчас готовлю о нём статью для Хабра). И если в исходных данных были единицы измерения из модуля pint, то они тоже будут сохранены и правильно обработаны в результате.
Что же касаемо арифметики - то вот она то как раз ни с какими единицами измерения не работает. В "чистой" математике всё равно, с чем ты имеешь дело. Но в физике и инженерии совершенно не так - тут нельзя применять математические методы таким образом, что бы в результате разложения паровоза получились слоны и канарейки. Вот для того, что бы контролировать физическую правильность математических выкладок, и предназначен модуль pint.
vadimr
13.08.2022 14:00Это очень упрощённое понимание физики и инженерии.
Начните с того, что попробуйте ввести единицы измерения для бесконечно малых величин. Потом можно попробовать последовательно ввести единицы измерения в квантовую механику, и в итоге свести её в один математический аппарат с теорией относительности ;)
MAK74 Автор
13.08.2022 14:33Квантовая механика это совершенно особая тема. Я же писал об обычной инженерии, имеющей дело с макрообъектами, а не с микромиром
vadimr
13.08.2022 14:40Ну когда как. Сейчас квантовая электроника и квантовая оптика образуют вполне весомую часть в общем объёме инженерных расчётов. В России особенно квантовая оптика активно развивается.
Но я не настаиваю именно на квантовой механике. Просто хочу сказать, что сложные физические расчёты – непростые вещи чисто в вычислительном отношении.
Taus
13.08.2022 16:31Фишки с единицами измерений как раз очень помогают. Если функция зависит сложным образом от величины X (сложнее степенной функции), то величина X должна быть безразмерной. К тому же, это является хорошей проверкой результата на ошибки после алгебраических преобразований.
Наверное, единственная используемая функция, в которую мы подставляем размерную величину, - это логарифм, то есть dB и близкие к нему. Правильнее было бы вычислять логарифм отношения X к размерному референсному значению. Но, потом мы чаще сравниваем значения dB относительно друг друга, а не абсолютные.vadimr
13.08.2022 16:38Если функция зависит сложным образом от величины X (сложнее степенной функции), то величина X должна быть безразмерной
Это большое заблуждение. Допустим, величина X – это дальность в метрах по данным локации космического аппарата, а функция – большая полуось его орбиты тоже в метрах, построенная по результатам применения статистических фильтров к данным нескольких таких локаторов (с помехами), модели гравитационного поля Земли, модели атмосферы, и т.д. и т.п. Величина X может при этом даже и не войти в результат, если фильтр рассудит, что это помеха.
Я чего-то даже сам задумался, какую размерность имеет измерение физической величины, умноженное на статистический весовой коэффициент. 100 километров с вероятностью 0.5 – это то же самое, что 50 километров, или всё же нет?
Инженерная практика – это очень часто математическая статистика в том или ином виде.
Taus
13.08.2022 16:48+1Если функция требует подстановки значений в метрах, то в неё уже неявно зашита константа, которая приводит метры в безразмерную величину. Каким образом статистические фильтры могут влиять на размерность величины?
100 километров с вероятностью 0.5 – это то же самое, что 50 километров, или всё же нет?
Вероятность - безразмерная величина как раз для того, чтобы можно было её на что угодно умножать. "100 км с вероятностью 0.5" - это уже не просто число с размерностью, сама фраза имеет значение в каком-то контексте.
vadimr
13.08.2022 17:07Не понял Вашу реплику.
Давайте для простоты возьмём конкретный пример. Мы измерили одно и то же расстояние 3 раза, первый раз получилась гипотеза 1 метр с апостериорной мощностью критерия 0.8, второй раз получилась гипотеза 1.2 метра с мощностью критерия 0.7, и третий раз получилась гипотеза 0.9 метра с мощностью критерия 0.9. Какую размерность в данном случае имеет байесовская оценка и собственно результат измерения?
По Вашим словам (как я их понял) получается, что меряли метры, а получили безразмерный результат.
Taus
13.08.2022 17:35+1Про байесовские методы обработки данных почти ничего не знаю. В случае когда вы все величины измеряете в метрах, то и результат измерения будет в метрах, дополненный информацией о распределении случайной величины.
Я же утверждаю, что после замены всех единиц измерения в примере с метров на, например, герц, включая шум, результат в числах не поменяется.
kimor
13.08.2022 12:47огромное количество различных библиотек (модулей), написанных как на самом питоне, так и на более быстрых "профессиональных" языках С/С++ и Фортран.
Судя из написанного, Питон по мнению автора язык непрофессиональный. Дальше читать не стал.
MAK74 Автор
13.08.2022 12:49Я не программист - поэтому могу и ошибаться в том, что профессиональные программисты не пишут на Питоне операционные системы, антивирусы, компиляторы и прочие пакеты прикладных программ. Если обидел профессионала - приношу свои извинения. Но хотелось бы получить конкретные примеры профессиональных программных продуктов, написанных на Питоне...
vadimr
13.08.2022 13:39Ну уж, во всяком случае, побольше частей современных ОС написано на питоне, чем на фортране.
buratino
13.08.2022 16:06ну назовите хотя бы одну часть ос, написанную на питоне.
Только именно ос, а не приложения под ос
vadimr
13.08.2022 16:15Странный вопрос. find / -name "*.py"
virt-manager, например, написан на питоне.
buratino
13.08.2022 19:42Какие буквы вам непонятны в "The virt-manager application is a desktop user interface"?
vadimr
13.08.2022 20:31-1А какие буквы вам непонятны в "часть ОС"? Это одна из важнейших частей пользовательского интерфейса операционной системы.
buratino
13.08.2022 21:31-1читайте доки что есть application и что есть operating system
не говоря уже об утверждении, что virt-manager есть одна из важнейших частей пользовательского интерфейса
kimor
14.08.2022 12:22Как-то Вы очень странно понимаете смысл слова профессиональный. Профессиональный от слова профессия. Видимо, мы учили разные русские языки в школе...
MAK74 Автор
14.08.2022 12:45Может быть, может быть... Я, всё-таки, русский только на половину и всю жизнь прожил в Молдавии ;)
kimor
14.08.2022 12:49Гадая что Вы хотели сказать говоря "непрофессиональный", единственное что мне приходит в голову, что он используется только для обучения, как в настоящее время, например, Паскаль. Про Питон такого точно сказать нельзя. Старайтесь быть точнее в формулировках.
MAK74 Автор
14.08.2022 13:02Посыпаю голову пеплом, хотя сказать я хотел совсем не это. Я предполагал, что Питон (ввиду его простоты) используют не программисты, а специалисты других профессий, которым надо что-то быстро напрограммировать для своей работы (сам такой). Воспринимаю Питон как потомка Бейсика (до знакомства с Питоном, я для тех же целей использовал VB6/VBA/VBS).
alt78
13.08.2022 17:29Пробовал использовать pint в работе, впечатления негативные.. Я иногда делаю физические расчеты. Пробовал делать их с pint, неудобно - громоздкий вывод, код распухший. Это оправдано только если код в прод, если надо быстро что-то проверить - неудобно.
Вернулся в SMath.
mixas-f
14.08.2022 13:03Не очень понятно, на какую аудиторию эта статья рассчитана? Если на школьника, то есть куча роликов, куда более наглядных. А для студента - материал вроде бы чересчур примитивен. Или я не прав?
MAK74 Автор
14.08.2022 13:09Я рассчитывал не на школьника и не на студента - а на такого же инженера непрограммистской специальности, которым являюсь и сам. Которому, тем не менее, в работе периодически надо что-то по-быстрому посчитать.
Что же касаемо кучи роликов, то я их как раз не люблю смотреть - привык пользоваться печатной документацией. Хотя бы потому, что из ролика код невозможно скопипастить ;) И предполагаю, что я не один такой
red_dragon
14.08.2022 16:07193 терагерца воспринимается человеком более естественно и понятно, чем 193414489032258 герц..
Вот тут прямо долго силился понять. Если всё, что после 193 не значимо, почему не использовать экспоненциальную запись 193Е14. Если же Вы считаете, что положение точки в числе, влияет на его читаемость, то это очень спорно.
sargon5000
15.08.2022 06:46Насчёт т определения метра автор здорово заблуждается. Метр — длина пути, проходимого светом в вакууме за интервал времени 1⁄299 792 458 секунды
Dukarav
надо бы упомянуть
1
2
а так же ряд других решений в matcad, RUST и т.п.
MAK74 Автор
Не вижу смысла писать и о других решениях - статья ведь конкретно о Python. Тем более, что про RUST я вообще ничего не знаю