New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make float.__floordiv__
return an int
#103445
Comments
Several core developers on the linked Discourse thread were skeptical about this proposal for various technical reasons. We shouldn't make this change without carefully considering these objections, and that will probably need a PEP. |
I think that people definitely should read the Discourse thread to make up their mind. |
Regardless of the desirability or not of an A critical part of any backwards compatibility mechanism would be a way for developers to opt-in to the new behaviour at a time of their choosing during the usual two-Python-version transition period. I just don't see a solution to this that doesn't involve either significant complexity in the Python core ( |
I don't think this requires any compatibility mechanism bigger than the non-togglable one I outlined in the document. When the random.seed function restricted the types it takes, and random.sample started rejecting sets and dicts, there was some transition period but no toggle between the old and the new behavior was introduced. It was the former one, right up until it was the new one. This is the most evident changes I could cite from my perspective, but there are surely dozens of other examples in various other parts of python. I seriously doubt this change would break any more code than these changes to the random module did. Not to mention the deafening lack of documentation about this : nowhere in the doc is there any mention that Why would an undocumented behavior with such little impact require such an extensive adaptative mechanism ? |
I'm afraid that that section of the document is rather unclear to me. Could you please outline (here, not in the document) precisely which code (and under what conditions) would be expected to issue a |
It would be right about here (and the same in the float_divmod function, but let's keep that one on the side while we work the floordiv case). In a second period of time, if we want to be extra-careful, we can have those ifs emit the warning and return the float-converted value, while the else (the normal behavior for non-infinity values of the And then after the deprecation period, we would remove those ifs and let the PyLong_FromDouble exceptions take care of it (or make the ifs raise the exceptions if we want to word them differently). Should you consider that to be insufficient, I presume it would be because of the other possible breaking points than inf and nan being returned. So these would only be for direct type checks on the floorquotient using |
Sorry, I meant which Python code. I'm asking about the user-visible behaviour change, not the implementation. That is, under what conditions should a Python user expect a
Indeed it's the type change that concerns me much more than the behaviour of NaNs or infinities. The ramifications of that type change aren't limited to direct type checking in user code. As a random example, consider this NumPy-using session: Python 3.10.10 (main, Feb 10 2023, 08:56:54) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> (np.arange(1000000) * (1e40 // 1e10)).dtype
dtype('float64')
>>> (np.arange(1000000) * int(1e40 // 1e10)).dtype
dtype('O') The second result is the result that we'd get under your proposal after the type change. And that's a big difference: an efficient array of 1 million packed floats has become an inefficient array of pointers to unboxed integers. That's the sort of change which should not occur silently. |
Here's another example where an integer-valued float being replaced by an int is far from innocuous: >>> x = 9.223372036854775e+18
>>> np.arange(3) * x / x
array([0., 1., 2.])
>>> y = int(x)
>>> np.arange(3) * y / y
array([ 0.00000000e+00, 1.00000000e+00, -2.22044605e-16]) Note that last value in the result - in one case it's |
Yes, but in other words, an array of imprecise values has become more precise. If developers (or modules, Numpy in this case) want to ignore that precision they should do so themselves, Python shouldn't crop things in their place. For me that's a feature, not a bug - and I'll note it only degrades performance and does not yield new errors.
I'm afraid I don't understand precisely how the problem happens. It's very weird that a calculation involving less floats and more ints makes it less accurate. It seems to be in the conversion of But of course if I misunderstood the second behavior it may be another bag of beans altogether. |
This comment was marked as abuse.
This comment was marked as abuse.
@Gouvernathor There is enough disagreement about this proposal that you will need to finish your PEP and get it submitted for this change to make it into Python. |
Feature or enhancement
int.__floordiv__
andfloat.__floordiv__
are the only two builtin implementations of the//
operator.This is to make
float.__floordiv__
return an int, so that the//
operator always returns an int when used on builtin types.Pitch
Opens the result of a floor-division involving float to the int API, which includes all the int methods on the one part, and the ability to be used in range, slices, list/tuple multiplication... on another part.
Floor division was first described as a true division followed by a call to
math.floor
, which got broken in PEP 3141 which changed math.floor's return type but seemingly forgot to changefloat.__floordiv__
's as well. This puts them back together.Read the PEP draft - though this may not require a PEP - for a more fuller and detailed rationale.
Previous discussion
Make
float.__(i/r)floordiv__
return an int on Ideas.The text was updated successfully, but these errors were encountered: