is something wrong with evaluation of Rationals?

52 views
Skip to first unread message

Chris Smith

unread,
Mar 30, 2018, 2:37:57 AM3/30/18
to sympy
Is this expected behavior for evaluating Rationals:

Rational of a string produces the exact decimal as a fraction:

>>> Rational('.975159')
975159/1000000

evaluation is going to be affected by rounding

>>> Rational('.975158').n(2)
0.97
>>> Rational('.975159').n(2)
0.98

But why is the digit affecting rounding in the 6th decimal position when we are trying to evaluate to the 2nd position? And I would have expected the split to be much closer to 5000 than 5158.

/c

Isuru Fernando

unread,
Mar 30, 2018, 4:24:02 AM3/30/18
to sy...@googlegroups.com
Part of it is a bug and part of it is a feature.

First the bug, https://github.com/sympy/sympy/blob/7524499458cf114b32e3aa6e8acdb77e846111f9/sympy/core/evalf.py#L1264 needs to be changed. It should be changed from from_rational(x.p, x.q, prec) to from_rational(x.p, x.q, prec, rnd). Otherwise round down is used instead of round nearest.

This doesn't affect much though. same phenomena happens at 5128 instead of 5158.

Now for the feature part.
a.n(2) doesn't guarantee you that the result will be rounded nearest to 2 decimal digits. a.n(2) only guarantees that the internal representation of  |a-a.n(2)|  < 0.5e-2.

Here's what sympy does.
dps = 2 (digits) is converted to prec=10 (bits)
.n routine first evaluates the rational with prec+4 bits and then rounds the result.

Larger rational is rounded to   p=15977*2**-14 = 0.9751586914...
Smaller rational is rounded to  q=15966*2**-14 = 0.9750976563...

In the round down case 5159 is rounded down to p and 5158 is rounded down to q
In the round to nearest case 5129 is rounded to p while 5128 is rounded to q.

Then sympy normalizes these mpfs to 10 bits.

There are now 2 choices
Larger float is rounded nearest to   r = 997*2**-10 = 0.9755859375
Smaller float is rounded nearest to s = 996*2**-10 = 0.9746093750

These two are the results you get, but SymPy prints only 2 decimal digits of the numbers and therefore prints 0.98 for the larger and 0.97 for the smaller.

There was a similar discussion in issue https://github.com/sympy/sympy/issues/12038

Isuru

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscribe@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/f9dc2400-5277-4ed1-ad80-00fa5b12bd6e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Smith

unread,
Mar 30, 2018, 1:00:18 PM3/30/18
to sympy
should 'rational with prec+4' be `prec+5'? It would take at most 5 binary digits to get you to the next decimal digit, wouldn't it?
Reply all
Reply to author
Forward
0 new messages