首先,我想指出我总共sympy
个菜鸟。
我尝试使用此sympy
表达式创建Custom Formula-based Measurement类:
from sympy import Symbol, S, floor, sympify, Float
SU = Symbol('millimeter')
exp = S(20.0) + floor((((SU-S(212.5)) / S(10.0))) / S(0.5)) * S(0.5)
我面临的问题是,对于相同的SU
,我会根据表达式的计算方式得到不同的结果。这就是我的意思:
>>> exp.subs(SU, 215)
20.0000000000000
>>> exp.evalf(subs={SU: 215})
0.e+1 #This is actually 16.0 when: float(exp.evalf(subs={SU: 215}))
更有趣的是,只有SU
介于[213:217]之间(当我希望结果为20.0
时),问题才存在
对于其余的值,其罚款(AFAIK)
>>> exp.subs(SU, 212)
19.5000000000000
>>> exp.evalf(subs={SU: 212})
19.50
>>> exp.subs(SU, 218)
20.5000000000000
>>> exp.evalf(subs={SU: 218})
20.50
对这种奇怪行为的任何想法?
答案 0 :(得分:3)
这是由于精度值不正确造成的。该错误是reported,已在GitHub上可用的当前版本的SymPy中得到纠正; SymPy的版本> 1.1.1不会有这个错误。
在srepr
的输出上使用subs
提供了一些解释:
x = Symbol('x')
srepr((floor(x)+20).evalf(subs={x:0.5}))
输出为Float('16.0', precision=1)
。这是二进制精度。 SymPy认为floor
的输出恰好为零,只有一位精度。因此它随后截断相加的+20,最接近2的幂。
当然,这是一个错误。有几个与Float类和舍入相关的未解决问题,例如this one;他们可能是相关的。
解决方法是避免evalf(subs=dict)
构建(甚至记录了吗?)。使用自然顺序中的方法:替换,然后评估,给出正确的结果:
srepr((floor(x)+20).subs({x:0.5}).evalf())
"Float('20.0', precision=53)"