如何将evalf()应用于symengine.py中的表达式?

时间:2017-07-18 12:48:47

标签: python numpy sympy symengine

我们在python包evalf()中找不到任何symengine。有没有?

我们问题的更详细解释。

我们正在尝试切换到symengine而不是sympy,因为我们认为必要的加速。我们使用符号代数工具来解决在组合随机结构生成中具有应用的优化问题。

经过一些关于同情的测试后,我们发现解决一些“无辜的”优化问题需要在范围1e+24及更远的范围内进行中间计算(但最终它们最终会提供正确的答案)。然后我发现我滥用了sympy的函数subs(),因为它不如使用替换字典的evalf()精确。

这个问题在函数subs:

的手册中有所描述
If the substitution will be followed by numerical
evaluation, it is better to pass the substitution to
evalf as

>>> (1/x).evalf(subs={x: 3.0}, n=21)
0.333333333333333333333

rather than

>>> (1/x).subs({x: 3.0}).evalf(21)
0.333333333333333314830

因为前者将确保所需的精度水平 获得。实际上,使用标准sympy.subs()函数替换e + 24,或者symengine.subs()抛出无穷大,尽管e + 24仍然在numpy.float64的范围内,我怀疑它是我的标准类型当我调用内置的float(...)函数时,机器会进入。

我们知道"lambdify",如果你做重复替换并想要高数值精度,这是推荐的步骤,但这将是下一步。我们无法使用python解释器的手册,因为代码是预编译的,而且在互联网上也很难找到任何代码。查看内容也没有帮助(但也许我错过了一些东西)。

1 个答案:

答案 0 :(得分:1)

还没有关于symengine的evalf。以下是如何实现上述目标的,

In [14]: (1/x).subs({x: 3}).n(73, real=True)
Out[14]: 0.333333333333333333333

请注意,如果你喜欢下面的内容,它将以精度53(15位十进制数字)

进行替换
In [15]: (1/x).subs({x: 3.0}).n(73, real=True)
Out[15]: 0.333333333333333314830

您可以使用Float(3.0, dps=21)而不是3.0的潜水艇以更高的精度进行计算。下面的例子适用于symengine和sympy。

In [16]: (1/x).subs({x: Float(3.0, dps=21)})
Out[16]: 0.333333333333333333333

请注意,symengine中的.n()更喜欢二进制数字而不是十进制数字的精度,并且需要为真实域提供real=True,否则它会假设复杂并且为您提供一个复数虚部0.,比real=True慢一点。