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