简体   繁体   中英

Different sympy expression results

First I want to point out that I'm a total sympy noob.

I'm trying to create a Custom Formula-based Measurement class with this sympy expression:

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)

The problem I face is that for the same SU I get different result based on the way the expression is evaluated. Here is what I mean:

>>> 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}))

More interestingly the problem exists only when SU is between [213:217] (when I expect the result to be 20.0 ) For the rest of the values its fine (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

Any Ideas for this strange behavior ?

This was due to incorrect precision values. The bug was reported and is already corrected in the current version of SymPy available on GitHub ; the versions of SymPy > 1.1.1 will not have this bug.


Using srepr on the output of subs provides some explanation:

x = Symbol('x')
srepr((floor(x)+20).evalf(subs={x:0.5}))

The output is Float('16.0', precision=1) . This is binary precision. SymPy thinks that the output of floor , when it happens to be zero, has only one bit of precision. So it subsequently truncates the added +20 accordingly, to nearest power of 2.

Of course, this is a bug. There are several open issues related to Float class and rounding, such as this one ; they may be related.

The workaround is to avoid evalf(subs=dict) construction (is it even documented?). Using the methods in the natural order: substitute, then evaluate, gives correct results:

srepr((floor(x)+20).subs({x:0.5}).evalf())
"Float('20.0', precision=53)"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM