ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SymPy 物理量系统实战:Quantity 类与 convert_to 单位换算完全指南

SymPy 物理量系统实战:Quantity 类与 convert_to 单位换算完全指南 SymPy 物理量系统实战Quantity 类与 convert_to 单位换算完全指南【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympySymPy 的sympy.physics.units模块提供了一套完整的量纲分析与单位系统框架其核心对象是Quantity物理量配套工具函数convert_to负责在不同单位之间进行换算。本篇指南以 quantities.rst 文档为主体结合仓库中 quantities.py 与 util.py 的源码实现系统讲解如何定义物理量、解析其属性维度、比例因子、缩写、在不同单位系统间完成换算并深入convert_to的矩阵求解原理。读完本文你将能够熟练定义自定义物理量、用convert_to完成任意兼容单位间的换算并理解 SymPy 单位模块底层的工作机制。一、物理量Quantity是什么SymPy 将物理量抽象为既可以表示计量单位如 meter、second、也可以表示物理常数如speed_of_light或通用量的一类对象。其类定义位于 quantities.pyclass Quantity(AtomicExpr): Physical quantity: can be a unit of measure, a constant or a generic quantity. Quantity继承自AtomicExpr具有以下关键数学属性见 quantities.pyis_commutative True参与乘法时可交换is_real True、is_nonzero True数值上视为实数且非零is_number False它本身不是纯数字_diff_wrt True可以对其求导is_physical_constant False默认不是物理常数PhysicalConstant子类才将其置为True。一个量在 SymPy 表达式中表现为数值因子 × 单位的形式例如3*meter、299792458*meter/second。所有量除单位系统与前缀外都可以直接嵌入普通 SymPy 表达式中参与运算这正是单位模块与 CAS 核心无缝集成的基础。二、构造一个物理量__new__的参数体系Quantity通过__new__构造其完整签名见 quantities.py为Quantity(name, abbrevNone, latex_reprNone, pretty_unicode_reprNone, pretty_ascii_reprNone, mathml_presentation_reprNone, is_prefixedFalse, **assumptions)各参数含义如下参数类型默认值说明namestr或Symbol必填量的名称传入字符串会自动转为Symbolabbrevstr或Symbol等于name量的缩写符号常用于打印输出latex_reprstrNone自定义 LaTeX 打印表示pretty_unicode_reprstrNoneUnicode 漂亮打印表示pretty_ascii_reprstrNoneASCII 漂亮打印表示mathml_presentation_reprstrNoneMathML 展示表示is_prefixedboolFalse是否带前缀如 kilogram 带 kilo 前缀构造出的对象内部保存_name、_abbrev及各类打印表示字段见 quantities.py。仅构造一个Quantity还不足以让它具有物理意义——你还需要通过set_global_relative_scale_factor把它与参考量关联起来见下文。测试用例 test_quantities.py 演示了标准做法q Quantity(q1) q.set_global_relative_scale_factor(S(5000), meter) assert q.convert_to(m) 5000*m # 自定义量可按比例换算到 meter assert q.dimension time # 维度自动继承自参考量2.1 定义全局相对比例因子set_global_relative_scale_factor(scale_factor, reference_quantity)用于声明该量等于 reference_quantity 的多少倍该比例关系跨所有单位系统有效见 quantities.py。其实现要点将比例因子sympify为 SymPy 表达式若比例因子是Prefix前缀对象如kilo自动把_is_prefixed置为True将表达式中所有Prefix替换为对应的数值比例因子Prefix.scale_factor把(scale_factor, reference_quantity)存入全局映射同时建立量 → 参考量的维度等价映射。测试 test_util.py 中有一个经典例子先定义英亩与平方英尺的换算关系再基于它定义第二个量验证链式换算acre_in_ft Quantity(acre) acre_in_ft.set_global_relative_scale_factor(43560, ft**2) assert convert_to(acre_in_ft, m**2) 316160658*meter**2/78125 acre_in_acre Quantity(acre_in_acre) acre_in_acre.set_global_relative_scale_factor(1, acre_in_ft) assert convert_to(acre_in_acre, m**2) 316160658*meter**2/781252.2 物理常数子类PhysicalConstantquantities.py 中定义了PhysicalConstant(Quantity)仅多了一个类属性is_physical_constant True。speed_of_light、avogadro_constant等常数均属此类。单位系统在枚举非前缀单位时会通过is_physical_constant过滤掉常数见 unitsystem.py。三、Quantity 的核心属性与方法Quantity暴露了一组属性与方法构成日常使用的主要接口3.1 属性name返回Symbol形式的量名称见 quantities.pyabbrev返回表示单位缩写的Symbol见 quantities.pydimension返回该量在默认单位系统当前为 SI中的维度委托给UnitSystem.get_quantity_dimension见 quantities.pyscale_factor返回该量相对规范单位的整体量级即UnitSystem.get_quantity_scale_factor(self)见 quantities.pyfree_symbols恒为空集——物理量不包含自由符号见 quantities.pyis_prefixed指示该量是否带前缀如kilogram为True而gram为False见 quantities.py。测试 test_quantities.py 验证了这些属性的行为u Quantity(u, abbrevom) u.set_global_relative_scale_factor(S(2), meter) assert u.name Symbol(u) assert u.abbrev Symbol(om) assert u.scale_factor 2 u Quantity(u, abbrevikm) u.set_global_relative_scale_factor(3*kilo, meter) assert u.scale_factor 3000注意set_global_relative_scale_factor(3*kilo, meter)中传入的kilo前缀会被自动展开为 1000因此比例因子是 3000。3.2 换算方法convert_toQuantity实例方法convert_to(other, unit_systemSI)是模块最常用的入口之一见 quantities.py from sympy.physics.units import speed_of_light, meter, second speed_of_light.convert_to(meter/second) 299792458*meter/second from sympy.physics.units import liter liter.convert_to(meter**3) meter**3/1000它内部只是转调util.convert_to核心换算逻辑都集中在 util 模块见下一节。3.3 特殊求值行为Quantity还重写了若干内部求值方法见 quantities.py_eval_is_positive恒真、_eval_is_constant恒真、_eval_Abs返回自身量对自身取绝对值不变、_eval_subs在替换目标为Quantity时阻止替换以及自定义的_latex打印逻辑。四、单位换算核心convert_to顶层函数convert_to(expr, target_units, unit_systemSI)定义于 util.py是本次文档的核心内容。它的功能是当维度兼容时把expr中所有单位与量都表示为target_units因子的组合。4.1 基本用法 from sympy.physics.units import speed_of_light, meter, gram, second, day from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant from sympy.physics.units import kilometer, centimeter from sympy.physics.units import gravitational_constant, hbar from sympy.physics.units import convert_to convert_to(mile, kilometer) # 英里 → 千米精确有理数 25146*kilometer/15625 convert_to(mile, kilometer).n() # 转浮点 1.609344*kilometer convert_to(speed_of_light, meter/second) 299792458*meter/second convert_to(day, second) 86400*second convert_to(3*newton, kilogram*meter/second**2) 3*kilogram*meter/second**2 convert_to(atomic_mass_constant, gram) 1.660539060e-24*gram目标单位可以是单个量也可以是列表/元组集合源码在 util.py 中会把非可迭代的单个目标统一包装为列表 convert_to(speed_of_light, [meter, second]) 299792458*meter/second convert_to(3*newton, [centimeter, gram, second]) 300000*centimeter*gram/second**2甚至可以换算到普朗克单位制以引力常数、光速、约化普朗克常数为基准 convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n() 7.62963087839509e-20*hbar**0.5*speed_of_light**0.5/gravitational_constant**0.54.2 参数说明参数类型默认值说明exprSymPy 表达式必填待换算的表达式可以是量、量的乘积/幂/和target_units量 或 量的列表/元组/Tuple必填目标单位集合表达式将化为这些单位的因子组合unit_systemstr或UnitSystemSI所用单位系统默认 SIunit_system参数通过UnitSystem.get_unit_system解析见 unitsystem.py传入UnitSystem实例时直接使用传入字符串时从已注册的单位系统字典中查找若不存在则抛出ValueError并列出当前支持的系统名称。4.3 底层原理量纲矩阵求解convert_to的实现分为几个关键步骤见 util.py处理加法结构若表达式是Add则逐项递归换算handle_Adds若表达式是加法整体的幂先换算底数再取幂。这保证了2*kilometer 3*mile这类混合加法也能正确换算。符号化与函数合并对表达式sympify化若是Function先together()合并。替换量对象对非纯Quantity但包含Quantity的表达式逐一把每个Quantity替换为其convert_to结果。构建量纲依赖矩阵辅助函数_get_conversion_matrix_for_expr见 util.py计算目标单位维度在规范量纲基下的依赖矩阵camat与表达式的维度依赖向量exprmat然后调用camat.solve(exprmat)求解目标单位的指数向量。若目标单位维度空间不覆盖表达式维度或矩阵不可逆NonInvertibleMatrixError则直接原样返回表达式——这就是维度不兼容时不做换算的实现机制。合成结果get_total_scale_factor递归累计整个表达式的总比例因子最后用指数向量把各目标单位以(1/scale_factor(u)*u)**p的形式相乘乘上总比例因子得到最终结果。测试 test_util.py 对该函数做了非常全面的验证包括维度不兼容时原样返回convert_to(3*newton, meter/second) 3*newton无理数换算convert_to(radians, degree) 180*degree/pi混合加法convert_to(2*kilometer/hour 3*mile/hour, meter/second) 53344*meter/(28125*second)幂次换算convert_to(inch**2, meter**2) 16129*meter**2/25000000幂次不可合并的表达式保持原样对应 issue 26263、27812。4.4 维度检查辅助函数check_dimensionsutil.py 还提供了check_dimensions(expr, unit_systemSI)检查表达式中所有加法项是否具有相同的基本维度若不一致则抛出带详细维度信息的ValueError。同时它会清除因替换引入的乘法常数如2*length还原为length。测试 test_util.py 验证了典型场景assert check_dimensions(newton*meter joule) joule meter*newton raises(ValueError, lambda: check_dimensions(length time)) raises(ValueError, lambda: check_dimensions(meter second))错误信息形如addends have incompatible dimensions: (((Dimension(length, L), 1),), ((Dimension(time, T), 1),))。五、配合单位系统UnitSystem使用Quantity的dimension与scale_factor属性都依赖默认单位系统——即 unitsystem.py 中的UnitSystem.get_default_unit_system()当前固定返回SI。这意味着所有量的维度解析与比例因子计算默认在 SI 基准下进行单位系统本质上是维度系统 尺度概念由base_units基本单位、units其他单位与derived_units导出单位映射组成见 unitsystem.py可以通过UnitSystem.extend基于现有系统派生出新系统见 unitsystem.py。实际换算中SI 系统中SI.get_quantity_scale_factor(kilometer) 1000、SI.get_quantity_scale_factor(kilometer**2) 10**6这些均在测试 test_util.py 中得到验证。六、配套工具quantity_simplify与find_unit虽然本次文档正文聚焦Quantity与convert_to但同一个 util 模块还提供两个高频配套函数值得一并掌握6.1quantity_simplifyquantity_simplify(expr, across_dimensionsFalse, unit_systemNone)见 util.py将前缀展开为数值、并把同维度单位统一为规范量。默认在同一维度内化简设置across_dimensionsTrue后还能跨维度合并如5*joule/coulomb化简为5*volt此时必须显式指定unit_system否则抛ValueError。 from sympy.physics.units.util import quantity_simplify from sympy.physics.units.prefixes import kilo from sympy.physics.units import foot, inch, joule, coulomb quantity_simplify(kilo*foot*inch) 250*foot**2/3 quantity_simplify(foot - 6*inch) foot/2 quantity_simplify(5*joule/coulomb, across_dimensionsTrue, unit_systemSI) 5*volt跨维度化简在测试 test_util.py 中有完整覆盖包括ampere*ohm → volt、joule/second → watt、volt/ampere → ohm等一连串导出单位推导。6.2find_unitfind_unit(quantity, unit_systemSI)见init.py用于在sympy.physics.units命名空间中查找匹配的单位或维度名支持传入字符串、Quantity或Dimension三种形式 from sympy.physics import units as u u.find_unit(charge) [C, coulomb, coulombs, planck_charge, elementary_charge] u.find_unit(u.inch**3)[:9] [L, l, cL, cl, dL, dl, mL, ml, liter]七、实战小结综合全文使用 SymPy 物理量模块的推荐流程是查单位用find_unit确认目标单位在模块中的可用名称换算用convert_to(expr, target_units)或expr.convert_to(target)完成单位换算维度不兼容时函数会原样返回表达式而非报错可用check_dimensions主动检查加法项维度一致性定义自定义量Quantity(name, abbrev...)set_global_relative_scale_factor(scale, reference)即可把任意自定义量接入现有换算体系见 test_quantities.py化简需要统一前缀与同维度单位时使用quantity_simplify跨维度合并需指定across_dimensionsTrue与unit_system。相关源码与测试路径汇总核心类 quantities.py、换算工具 util.py、单位系统 unitsystem.py、模块导出init.py、测试用例 test_quantities.py 与 test_util.py。模块的完整使用说明与所有预定义单位、常数列表可进一步查阅 units 模块文档。【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表