Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-11 Thread Chris Smith
The question is whether we can, with limitations of binary representation, give a result that is consistent with what we would expect if using base-10 notation. The advantage that SymPy and Decimal have is that they know, by merit of values given at instantiation, what the last significant

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-11 Thread Oscar Benjamin
I think that Python's float.__round__ is correct. AIUI it rounds correctly based on the true value represented by the float: In [4]: round(1.05, 1) Out[4]: 1.1 In [5]: import decimal In [6]: decimal.Decimal(1.1) Out[6]: Decimal('1.100088817841970012523233890533447265625') That's

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Chris Smith
I am aware of how the numbers are stored but was overly optimistic that the shift could resolve this in all cases. It can't (and thanks for the correction). But my suggested alternative makes a significant difference in how often the problem arises: >>> bad=[] >>> for i in range(1,1000): ...

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Chris Smith
I am aware of how the numbers are stored and was overly optimistic that the shift could resolve this in all cases. It can't. But my suggested alternative makes a significant difference it how often the problem arises: >>> bad=[] >>> for i in range(1,1000): ... n = str(i)+'5' ... if

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Oscar Benjamin
The fact that the numbers are stored in binary is significant: In [16]: nums = [eval('1.%d5' % n) for n in range(10)] In [17]: nums Out[17]: [1.05, 1.15, 1.25, 1.35, 1.45, 1.55, 1.65, 1.75, 1.85, 1.95] In [18]: [round(n, 1) for n in nums] Out[18]: [1.1, 1.1, 1.2, 1.4, 1.4, 1.6, 1.6, 1.8, 1.9,

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Chris Smith
That floats are stored in binary is an implementation detail which need not prevent base-10 rounding to still work. The 2nd argument to round is intended to tell at which base-10 digit the rounding is to take place. By shifting that digit to the ones position and then doing the rounding one

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Aaron Meurer
The round() function used in that function comes from the C math standard library. Here is an implementation that is used if it isn't available. https://github.com/python/cpython/blob/a10d426bab66a4e1f20d5e1b9aee3dbb435cf309/Python/pymath.c#L72 Aaron Meurer On Wed, Apr 10, 2019 at 6:39 PM Aaron

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Aaron Meurer
Here is the Python implementation https://github.com/python/cpython/blob/a10d426bab66a4e1f20d5e1b9aee3dbb435cf309/Objects/floatobject.c#L917 It's possible you have found a bug in Python's round. I'm unclear how it is supposed to work. Aaron Meurer On Wed, Apr 10, 2019 at 6:28 PM Aaron Meurer

Re: [sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Aaron Meurer
Doesn't Python do rounding based on the binary representation of the float? I'm a little confused what "round to even" means in that case. Aaron Meurer On Wed, Apr 10, 2019 at 6:16 PM Chris Smith wrote: > > Python 3 implements "round to even on tie" logic so `round(12.5)` -> 12, not > 13. I

[sympy] rounding difference between Python 3 and SymPy

2019-04-10 Thread Chris Smith
Python 3 implements "round to even on tie" logic so `round(12.5)` -> 12, not 13. I have updated, in #16608 , the round function but there is a difference in how ties are detected. I shift the desired position to the ones position and then check for a