round / set_printoptions discrepancy
Hi, Is it expected/documented that np.round and np.set_printoptions do not output the same result on screen ? I tumbled into this running this code: import numpy as np mes = np.array([ [16.06, 16.13, 16.06, 16.00, 16.06, 16.00, 16.13, 16.00] ]) avg = np.mean(mes, axis=1) print(np.round(avg, 2)) np.set_printoptions(precision=2) print(avg) Which outputs: [16.06] [16.05] Is that worth a bug report or did I miss something ? I've been able to reproduce this on many windows/linux PCs with python/numpy releases from 2017 up to last week. Thanks.
On Fri, Sep 13, 2019 at 12:58 PM Irvin Probst <irvin.probst@enstabretagne.fr> wrote:
Hi, Is it expected/documented that np.round and np.set_printoptions do not output the same result on screen ? I tumbled into this running this code:
import numpy as np mes = np.array([ [16.06, 16.13, 16.06, 16.00, 16.06, 16.00, 16.13, 16.00] ])
avg = np.mean(mes, axis=1) print(np.round(avg, 2)) np.set_printoptions(precision=2) print(avg)
Which outputs:
[16.06] [16.05]
Is that worth a bug report or did I miss something ? I've been able to reproduce this on many windows/linux PCs with python/numpy releases from 2017 up to last week.
Thanks. _______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org https://mail.python.org/mailman/listinfo/numpydiscussion
Hi, I just want to add that you can use literal 16.055 to reproduce this:
import numpy as np np.set_printoptions(precision=2) np.array([16.055]).round(2) array([16.06]) np.array([16.055]) array([16.05])
I would think it has to do with "round to nearest even":
np.array(16.055) array(16.05) np.array(16.065) array(16.07) np.array(16.065).round(2) 16.07
But it's as if `round` rounded decimal digits upwards (16.055 > 16.06, 16.065 > 16.07), whereas the `repr` rounded to the nearest odd(!) digit (16.055 > 16.05, 16.065 > 16.07). Does this make any sense? I'm on numpy 1.17.2. (Scalars or 1length 1d arrays don't seem to make a difference). Regards, András
On 9/13/19 7:23 AM, Andras Deak wrote:
I just want to add that you can use literal 16.055 to reproduce this:
import numpy as np np.set_printoptions(precision=2) np.array([16.055]).round(2) array([16.06]) np.array([16.055]) array([16.05])
I would think it has to do with "round to nearest even":
np.array(16.055) array(16.05) np.array(16.065) array(16.07) np.array(16.065).round(2) 16.07
But it's as if `round` rounded decimal digits upwards (16.055 > 16.06, 16.065 > 16.07), whereas the `repr` rounded to the nearest odd(!) digit (16.055 > 16.05, 16.065 > 16.07). Does this make any sense? I'm on numpy 1.17.2. (Scalars or 1length 1d arrays don't seem to make a difference). Regards,
András
Isn't that just for consistency with Python 3 round()? I agree that the discrepancy with np.set_printoptions is not necessarily expected, except possibly for backwards compatibility. Phil
On 13/09/2019 14:05, Philip Hodge wrote:
Isn't that just for consistency with Python 3 round()? I agree that the discrepancy with np.set_printoptions is not necessarily expected, except possibly for backwards compatibility.
I've just checked and np.set_printoptions behaves as python's round:
round(16.055,2) 16.05 np.round(16.055,2) 16.06
I don't know why round and np.round do not behave the same, actually I would even dare to say that I don't care :) However np.round and np.set_printoptions should provide the same output, shouldn't they ? This discrepancy is really disturbing whereas consistency with python's round looks like the icing on the cake but in no way a required feature.  Irvin
On 9/13/19 8:45 AM, Irvin Probst wrote:
On 13/09/2019 14:05, Philip Hodge wrote:
Isn't that just for consistency with Python 3 round()? I agree that the discrepancy with np.set_printoptions is not necessarily expected, except possibly for backwards compatibility.
I've just checked and np.set_printoptions behaves as python's round:
round(16.055,2) 16.05 np.round(16.055,2) 16.06
I don't know why round and np.round do not behave the same, actually I would even dare to say that I don't care :) However np.round and np.set_printoptions should provide the same output, shouldn't they ? This discrepancy is really disturbing whereas consistency with python's round looks like the icing on the cake but in no way a required feature.
Python round() is supposed to round to the nearest even value, if the two closest values are equally close. So round(16.055, 2) returning 16.05 was a surprise to me. I checked the documentation and found a note that explained that this was because "most decimal fractions can't be represented exactly as a float." round(16.55) returns 16.6. Phil
On Fri, Sep 13, 2019 at 2:59 PM Philip Hodge <hodge@stsci.edu> wrote:
On 9/13/19 8:45 AM, Irvin Probst wrote:
On 13/09/2019 14:05, Philip Hodge wrote:
Isn't that just for consistency with Python 3 round()? I agree that the discrepancy with np.set_printoptions is not necessarily expected, except possibly for backwards compatibility.
I've just checked and np.set_printoptions behaves as python's round:
round(16.055,2) 16.05 np.round(16.055,2) 16.06
I don't know why round and np.round do not behave the same, actually I would even dare to say that I don't care :) However np.round and np.set_printoptions should provide the same output, shouldn't they ? This discrepancy is really disturbing whereas consistency with python's round looks like the icing on the cake but in no way a required feature.
Python round() is supposed to round to the nearest even value, if the two closest values are equally close. So round(16.055, 2) returning 16.05 was a surprise to me. I checked the documentation and found a note that explained that this was because "most decimal fractions can't be represented exactly as a float." round(16.55) returns 16.6.
Phil
_______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org https://mail.python.org/mailman/listinfo/numpydiscussion
Ah, of course, endless doubleprecision shenanigans...
format(16.055, '.30f') '16.054999999999999715782905695960'
format(16.55, '.30f') '16.550000000000000710542735760100'
András
See the notes section here. https://numpy.org/devdocs/reference/generated/numpy.around.html. This note was recently added in https://github.com/numpy/numpy/pull/14392 Eric On Fri, Sep 13, 2019 at 9:20 AM Andras Deak <deak.andris@gmail.com> wrote:
On Fri, Sep 13, 2019 at 2:59 PM Philip Hodge <hodge@stsci.edu> wrote:
On 9/13/19 8:45 AM, Irvin Probst wrote:
On 13/09/2019 14:05, Philip Hodge wrote:
Isn't that just for consistency with Python 3 round()? I agree that the discrepancy with np.set_printoptions is not necessarily expected, except possibly for backwards compatibility.
I've just checked and np.set_printoptions behaves as python's round:
round(16.055,2) 16.05 np.round(16.055,2) 16.06
I don't know why round and np.round do not behave the same, actually I would even dare to say that I don't care :) However np.round and np.set_printoptions should provide the same output, shouldn't they ? This discrepancy is really disturbing whereas consistency with python's round looks like the icing on the cake but in no way a required feature.
Python round() is supposed to round to the nearest even value, if the two closest values are equally close. So round(16.055, 2) returning 16.05 was a surprise to me. I checked the documentation and found a note that explained that this was because "most decimal fractions can't be represented exactly as a float." round(16.55) returns 16.6.
Phil
_______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org https://mail.python.org/mailman/listinfo/numpydiscussion
Ah, of course, endless doubleprecision shenanigans...
format(16.055, '.30f') '16.054999999999999715782905695960'
format(16.55, '.30f') '16.550000000000000710542735760100'
András _______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org https://mail.python.org/mailman/listinfo/numpydiscussion
On 13/09/2019 15:26, Eric Moore wrote:
See the notes section here. https://numpy.org/devdocs/reference/generated/numpy.around.html.
This note was recently added in https://github.com/numpy/numpy/pull/14392
Thanks, it indeed explains the discrepancy.
On 9/13/19 9:26 AM, Eric Moore wrote:
See the notes section here. https://numpy.org/devdocs/reference/generated/numpy.around.html.
This note was recently added in https://github.com/numpy/numpy/pull/14392
Eric
Hmm, but this example with 16.055 shows the note still isn't quite right. The doc suggests that the floating point error only matters for large values or large `decimals`, but this shows it also happens for small values. Makes sense now that I see the example. We should tweak the docstring. Also, I did make some notes in https://github.com/numpy/numpy/issues/14391 for how we could "fix" this problem efficiently. Unfortunately it's far from trivial to write a correct rounding algorithm, and I'm not sure it's worth the effort: The round error is comparable to normal floatingpoint error, and I don't think round is heavily used. Best, Allan
On Fri, Sep 13, 2019 at 9:20 AM Andras Deak <deak.andris@gmail.com <mailto:deak.andris@gmail.com>> wrote:
On Fri, Sep 13, 2019 at 2:59 PM Philip Hodge <hodge@stsci.edu <mailto:hodge@stsci.edu>> wrote: > > On 9/13/19 8:45 AM, Irvin Probst wrote: > > On 13/09/2019 14:05, Philip Hodge wrote: > >> > >> Isn't that just for consistency with Python 3 round()? I agree that > >> the discrepancy with np.set_printoptions is not necessarily expected, > >> except possibly for backwards compatibility. > >> > >> > > > > I've just checked and np.set_printoptions behaves as python's round: > > > > >>> round(16.055,2) > > 16.05 > > >>> np.round(16.055,2) > > 16.06 > > > > I don't know why round and np.round do not behave the same, actually I > > would even dare to say that I don't care :) > > However np.round and np.set_printoptions should provide the same > > output, shouldn't they ? This discrepancy is really disturbing whereas > > consistency with python's round looks like the icing on the cake but > > in no way a required feature. > > > > Python round() is supposed to round to the nearest even value, if the > two closest values are equally close. So round(16.055, 2) returning > 16.05 was a surprise to me. I checked the documentation and found a > note that explained that this was because "most decimal fractions can't > be represented exactly as a float." round(16.55) returns 16.6. > > Phil > > _______________________________________________ > NumPyDiscussion mailing list > NumPyDiscussion@python.org <mailto:NumPyDiscussion@python.org> > https://mail.python.org/mailman/listinfo/numpydiscussion
Ah, of course, endless doubleprecision shenanigans... >>> format(16.055, '.30f') '16.054999999999999715782905695960'
>>> format(16.55, '.30f') '16.550000000000000710542735760100'
András _______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org <mailto:NumPyDiscussion@python.org> https://mail.python.org/mailman/listinfo/numpydiscussion
_______________________________________________ NumPyDiscussion mailing list NumPyDiscussion@python.org https://mail.python.org/mailman/listinfo/numpydiscussion
participants (5)

Allan Haldane

Andras Deak

Eric Moore

Irvin Probst

Philip Hodge