[Numpy-discussion] round(numpy.float64(0.0)) is a numpy.float64

Robert Kern robert.kern at gmail.com
Tue Mar 27 01:52:35 EDT 2018


On Mon, Mar 26, 2018 at 10:03 PM, <josef.pktd at gmail.com> wrote:
>
> On Mon, Mar 26, 2018 at 10:29 PM, Robert Kern <robert.kern at gmail.com>
wrote:
> > On Mon, Mar 26, 2018 at 6:28 PM, Nathaniel Smith <njs at pobox.com> wrote:
> >>
> >> On Mon, Mar 26, 2018 at 6:24 PM, Nathaniel Smith <njs at pobox.com> wrote:
> >> > Even knowing that, it's still confusing that round(np.float64(0.0))
> >> > isn't the same as round(0.0). The reason is a Python 2 / Python 3
> >> > thing: in Python 2, round returns a float, while on Python 3, it
> >> > returns an integer – but numpy still uses the python 2 behavior
> >> > everywhere.
> >> >
> >> > I'm not sure if it's possible or worthwhile to change this. If we'd
> >> > changed it when we first added python 3 support then it would have
> >> > been easy (and obviously a good idea), but at this point it might be
> >> > tricky?
> >>
> >> Oh right, and I forgot: part of the reason it's tricky is that it
> >> really would have to return a Python 'int', *not* any of numpy's
> >> integer types, because floats have a much larger range than numpy
> >> integers, e.g.:
> >
> > I don't think that's the tricky part. We don't have to change anything
but
> > our implementation of Python 3's __round__() special method for
np.generic
> > scalar types, which would be straightforward. The only issue, besides
> > backwards compatibility, is that it would introduce a new inconsistency
> > between scalars and arrays (which can't use the Python ints). However,
> > that's "paid for" by the increased compatibility with the rest of
Python.
> > For a special method that is used for to interoperate with a Python
builtin
> > function, that's probably the more important consistency to worry about.
> >
> > As for the backwards compatibility concern, I don't think it would
matter
> > much. Everyone who has written code that expects round(np.float64(...))
to
> > return a np.float64 is probably already wrapping that with int()
anyways.
> > Anyone who really wants to keep the scalar type of the output same as
the
> > input can use np.around().
>
> same would need to apply for ceil, floor, trunc, I guess.

ceil and floor don't have __special__ methods for them; math.ceil() and
math.floor() do not defer their implementation to the type. math.trunc()
might (there is a __trunc__), but it looks like math.trunc(np.float64(...))
already returns an int.

I'm not suggesting changing np.ceil(), np.floor(), etc. Nor am I suggesting
that we change np.around(), np.round(), or the .round() method on scalar
types. Only .__round__().

> However, np.round has a decimal argument that I use pretty often and
> that needs to return a float
>
> >>> np.round(5.33333, 2)
> 5.3300000000000001
>
> Python makes the return type conditional on whether ndigits is used or not
> AFAICS.
> >>> round(5.33333, 0)
> 5.0
> >>> round(5.33333)
> 5

Sorry, I took that as a given. If someone followed my suggestion to
implement np.generic.__round__, yes, they I intended that they handle both
cases correctly.

But also, to reiterate, I'm not suggesting that we change np.round(). Only
the behavior of numpy scalar types under the builtin round() function.

--
Robert Kern
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20180326/09808375/attachment-0001.html>


More information about the NumPy-Discussion mailing list