SymPy:如何以其他表达式的形式返回表达式?
我对SymPy还比较陌生,有一个可能比较基础的问题。或者我可能只是误解了SymPy的用法。
有没有办法创建一个不是由基本元素(原子)表示的表达式,而是由其他表达式组合而成的呢?
举个例子:
>>> from sympy.physics.units import *
>>> expr1 = m/s
>>> expr2 = mile/hour
>>> expr1
m/s
>>> expr2
1397*m/(3125*s)
>>> expr1.in_terms_of([mile,hour]) #in my dreams?
3125*mile/(1397*hour)
>>>
顺便问一下:我能找到完整的SymPy文档的“官方”PDF(或其他可打印)版本吗?(我在工作中受到严格的网络使用限制,周末在家工作真的很累。)
更新:
这是我根据Prelude的建议得到的结果,不过这样用起来感觉不太舒服,可能不会被广泛使用。欢迎大家评论和吐槽。
def in_terms_of(self, terms):
expr2 = eval(str(self), physics.units.__dict__)
converter = {}
for term in terms:
term_expr = physics.units.__dict__[term]
coeff = term_expr.as_coeff_terms()[0]
unit = physics.units.Unit('my_'+term, term)
converter[term_expr/coeff] = unit/coeff
return str(expr2.subs(converter))
用法:
>>> x = in_terms_of('J',['gram','mile','hour'])
>>> x
'9765625000*mile**2*gram/(1951609*hour**2)'
>>> in_terms_of(x,['J'])
'J'
3 个回答
在sympy单位中,你可以通过除法将expr1转换为expr2:
In [120]: import sympy.physics.units as units
In [121]: expr1 = units.m / units.s
In [122]: expr2 = units.miles / units.hour
In [123]: a = (1397/3125) * expr1 / expr2
In [124]: a
Out[124]: 1
唯一的问题是,这样得到的结果是一个无量纲的数值。你也可以考虑使用Quantities这个包来处理这类问题:
In [125]: import quantities as pq
In [126]: a = pq.Quantity(1397/3125, 'm/s')
In [127]: a
Out[127]: array(0.44703999999999999) * m/s
In [128]: a.units = pq.mile / pq.hour
In [129]: a
Out[129]: array(1.0) * mi/h
还有一个叫Unum的工具。
我不知道sympy文档是否有PDF版本,但你可以尝试从他们的仓库下载,然后使用Sphinx来生成PDF。
还有一个叫做 quantities 的库:
In [1]: from quantities import *
In [2]: v = 1397*m / (3125*s)
In [3]: v
Out[3]: array(0.44704) * m/s
In [8]: v.units = mile/hour
In [9]: v
Out[9]: array(1.0) * mi/h
查看 sympy.physics.units 的源代码,你会发现所有的单位都是用米、千克、秒、安培、开尔文、摩尔和坎德拉这几种基本单位来定义的。这些就是基本单位。
比如,一英里被定义为5280英尺,而一英尺又被定义为0.3048米。
所以,任何使用非基本单位的表达式,都会把这些非基本单位替换成基本单位。
你可以定义自己的单位,当你需要用特定单位进行计算时,可以把这些单位代入表达式中:
import sympy.physics.units as units
from sympy import Rational
my_mile = units.Unit('my_mile', 'mile')
my_hour = units.Unit('my_hour', 'hour')
接着定义一个字典,用来把基本单位替换成你新定义的单位。
converter = {units.m: my_mile/Rational('1609.344'),
units.s: my_hour/Rational('3600')}
所有的计算都要使用基本单位。如果你想要用英里和小时来表示一个值,你可以把你的新单位代入表达式中。
v = 10*units.miles/units.hour
print v # = 2794*m/(625*s)
print v.subs(converter) # = 10*mile/hour
可以参考ars的回答来获取文档。Sympy的代码库在这里:https://github.com/sympy/sympy
在文档文件夹里有一个README文件,里面描述了如何创建html文档。