python - 如何解析和简化像 '3cm/µs² + 4e-4 sqmiles/km/h**2' 这样正确处理物理单位的字符串?

标签 python parsing sympy

我想将 3cm/µs² + 4e-4 sqmiles/km/h**2 这样的字符串拆分成它的 SI unit (在本例中,m/s**2)及其大小(以该单位的倍数表示)。

因为 sympy 提供了 parsing modulemany physical units and SI prefixes ,我想使用 sympy 是个好主意。但是实现这一目标的好方法是什么?我会编写如下算法,但我想避免重新发明方轮:

  • 将数字和字母(4e-4 类语法除外)和空格(除非它紧挨着显式运算符)之间的转换视为乘法,然后标记化
  • 用其 SI 表示替换每个非数字标记(同时检查 SI 前缀)
  • 将新表达式简化为 Magnitude * some SI units(在单位不一致时给出有意义的错误消息,例如 Cannot add m**2 to s)<

这可以通过现有手段轻松实现吗?或者如何最好地实现?

最佳答案

单位

一个解决方案是从 SymPy units 模块中收集所有单位,并使用它们来替换由 sympify

创建的符号
>>> import sympy.physics.units as u 
... subs = {} 
... for k, v in u.__dict__.items(): 
...     if isinstance(v, Expr) and v.has(u.Unit): 
...         subs[Symbol(k)] = v # Map the `Symbol` for a unit to the unit

>>> # sympify returns `Symbol`s, `subs` maps them to `Unit`s
>>> print sympify('yard*millimeter/ly').subs(subs)
127*m/1313990343414000000000

如果符号不在 units 中,它将被打印为未知符号(例如 barn)

>>> print sympify('barn/meter**2').subs(subs)
barn/m**2 

但您始终可以向 subs 字典中添加内容。

>>> subs[Symbol('almost_meter')] = 0.9*u.meter
... sympify('almost_meter').subs(subs)
0.9*m

SI 前缀的工作方式并不完全符合您的要求。您将需要添加一个乘号(或者希望它是像 km 这样明确实现的常用单位)。此外,由于它们不是 Unit 实例而是 Integer 实例,您必须将它们添加到 subs:

>>> import sympy.physics.units as u
... subs = {} 
... for k, v in u.__dict__.items(): 
...     if (isinstance(v, Expr) and v.has(u.Unit)) or isinstance(v, Integer): 
...         subs[Symbol(k)] = v 

>>> print sympify('mega*m').subs(subs)
1000000*m 

对于 unicode,您可能需要进行一些预处理。我不认为 SymPy 对 unicode 支持做出任何 promise 。

如果您实现新的 Unit,请考虑在 github 上向它们发出拉取请求。要编辑的文件应该是 sympy/physics/units.py

空格和隐式乘法

在 SymPy 的开发版本中,您可以找到假定隐式乘法的代码,其中写有适当的空格:

>>> from sympy.parsing.sympy_parser import (parse_expr,
... standard_transformations, implicit_multiplication_application)

>>> parse_expr("10sin**2 x**2 + 3xyz + tan theta",
...            transformations=(standard_transformations + 
...                             (implicit_multiplication_application,)))
3*x*y*z + 10*sin(x**2)**2 + tan(theta) 

安全

sympify 使用 eval 如果您打算将它用于面向网络的应用程序,则可以利用它!

关于python - 如何解析和简化像 '3cm/µs² + 4e-4 sqmiles/km/h**2' 这样正确处理物理单位的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15895819/

相关文章:

python - 子树中的节点总和(非二叉树)

PYTHON 从嵌套列表中删除元素

java - 如何使用 Jena 处理 DBpedia 页面的 rdf 版本?

c# - 将字符串解析为 DateTime,有时会增加 1 小时(时区)

python - 用 sympy 对方程进行数值计算

Python/Sympy三次方程三角解法

python - 如何使用 Python 读取图像文件?

ios - 适用于 iOS 的简单 XML 解析器 - Objective C

python - 如何用Python求解符号方程组?

python - 在python中创建数据库