Hello,
Is it normal, expected and desired that :
round(numpy.float64(0.0)) is a numpy.float64
while
round(numpy.float(0.0)) is an integer?
I find it disturbing and misleading. What do you think? Has it already been discussed somewhere else?
Best regards,
Olivier
numpy.float is an alias to the python float builtin.
https://github.com/numpy/numpy/issues/3998
On Thu, Mar 22, 2018 at 2:26 PM Olivier oc-spam66@laposte.net wrote:
Hello,
Is it normal, expected and desired that :
round(numpy.float64(0.0)) is a numpy.float64
while
round(numpy.float(0.0)) is an integer?
I find it disturbing and misleading. What do you think? Has it already been discussed somewhere else?
Best regards,
Olivier
NumPy-Discussion mailing list NumPy-Discussion@python.org https://mail.python.org/mailman/listinfo/numpy-discussion
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?
-n
On Thu, Mar 22, 2018 at 12:32 PM, Nathan Goldbaum nathan12343@gmail.com wrote:
numpy.float is an alias to the python float builtin.
https://github.com/numpy/numpy/issues/3998
On Thu, Mar 22, 2018 at 2:26 PM Olivier oc-spam66@laposte.net wrote:
Hello,
Is it normal, expected and desired that :
round(numpy.float64(0.0)) is a numpy.float64
while
round(numpy.float(0.0)) is an integer?
I find it disturbing and misleading. What do you think? Has it already been discussed somewhere else?
Best regards,
Olivier
NumPy-Discussion mailing list NumPy-Discussion@python.org https://mail.python.org/mailman/listinfo/numpy-discussion
NumPy-Discussion mailing list NumPy-Discussion@python.org https://mail.python.org/mailman/listinfo/numpy-discussion
On Mon, Mar 26, 2018 at 6:24 PM, Nathaniel Smith njs@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.:
In [4]: round(1e50) Out[4]: 100000000000000007629769841091887003294964970946560
In [5]: round(np.float64(1e50)) Out[5]: 1e+50
In [6]: np.uint64(round(np.float64(1e50))) Out[6]: 0
(Actually that last case illustrates another weird inconsistency: np.uint64(1e50) -> OverflowError, but np.uint64(np.float64(1e50)) -> 0. I have no idea what's going on there.)
-n
On Mon, Mar 26, 2018 at 6:28 PM, Nathaniel Smith njs@pobox.com wrote:
On Mon, Mar 26, 2018 at 6:24 PM, Nathaniel Smith njs@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().
-- Robert Kern
On Mon, Mar 26, 2018 at 10:29 PM, Robert Kern robert.kern@gmail.com wrote:
On Mon, Mar 26, 2018 at 6:28 PM, Nathaniel Smith njs@pobox.com wrote:
On Mon, Mar 26, 2018 at 6:24 PM, Nathaniel Smith njs@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.
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
(I'm currently using Python 3.4.4)
Josef
-- Robert Kern
NumPy-Discussion mailing list NumPy-Discussion@python.org https://mail.python.org/mailman/listinfo/numpy-discussion
On Mon, Mar 26, 2018 at 10:03 PM, josef.pktd@gmail.com wrote:
On Mon, Mar 26, 2018 at 10:29 PM, Robert Kern robert.kern@gmail.com
wrote:
On Mon, Mar 26, 2018 at 6:28 PM, Nathaniel Smith njs@pobox.com wrote:
On Mon, Mar 26, 2018 at 6:24 PM, Nathaniel Smith njs@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