__truediv__
and __itruediv__
?//
or a future division statement?input()
, compile()
, execfile()
, eval()
and exec
?The current division (/
) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the arguments are floats or complex. This makes expressions expecting float or complex results error-prone when integers are not expected but possible as inputs.
We propose to fix this by introducing different operators for different operations: x/y
to return a reasonable approximation of the mathematical result of the division (“true division”), x//y
to return the floor (“floor division”). We call the current, mixed meaning of x/y “classic division”.
Because of severe backwards compatibility issues, not to mention a major flamewar on c.l.py, we propose the following transitional measures (starting with Python 2.2):
//
operator will be available to request floor division unambiguously.from __future__ import division
, will change the /
operator to mean true division throughout the module.//
operator when appropriate, so as to completely avoid classic division.The classic division operator makes it hard to write numerical expressions that are supposed to give correct results from arbitrary numerical inputs. For all other operators, one can write down a formula such as x*y**2 + z
, and the calculated result will be close to the mathematical result (within the limits of numerical accuracy, of course) for any numerical input type (int, long, float, or complex). But division poses a problem: if the expressions for both arguments happen to have an integral type, it implements floor division rather than true division.
The problem is unique to dynamically typed languages: in a statically typed language like C, the inputs, typically function arguments, would be declared as double or float, and when a call passes an integer argument, it is converted to double or float at the time of the call. Python doesn’t have argument type declarations, so integer arguments can easily find their way into an expression.
The problem is particularly pernicious since ints are perfect substitutes for floats in all other circumstances: math.sqrt(2)
returns the same value as math.sqrt(2.0)
, 3.14*100
and 3.14*100.0
return the same value, and so on. Thus, the author of a numerical routine may only use floating point numbers to test his code, and believe that it works correctly, and a user may accidentally pass in an integer input value and get incorrect results.
Another way to look at this is that classic division makes it difficult to write polymorphic functions that work well with either float or int arguments; all other operators already do the right thing. No algorithm that works for both ints and floats has a need for truncating division in one case and true division in the other.
The correct work-around is subtle: casting an argument to float() is wrong if it could be a complex number; adding 0.0 to an argument doesn’t preserve the sign of the argument if it was minus zero. The only solution without either downside is multiplying an argument (typically the first) by 1.0. This leaves the value and sign unchanged for float and complex, and turns int and long into a float with the corresponding value.
It is the opinion of the authors that this is a real design bug in Python, and that it should be fixed sooner rather than later. Assuming Python usage will continue to grow, the cost of leaving this bug in the language will eventually outweigh the cost of fixing old code – there is an upper bound to the amount of code to be fixed, but the amount of code that might be affected by the bug in the future is unbounded.
Another reason for this change is the desire to ultimately unify Python’s numeric model. This is the subject of PEP 228 (which is currently incomplete). A unified numeric model removes most of the user’s need to be aware of different numerical types. This is good for beginners, but also takes away concerns about different numeric behavior for advanced programmers. (Of course, it won’t remove concerns about numerical stability and accuracy.)
In a unified numeric model, the different types (int, long, float, complex, and possibly others, such as a new rational type) serve mostly as storage optimizations, and to some extent to indicate orthogonal properties such as inexactness or complexity. In a unified model, the integer 1 should be indistinguishable from the floating point number 1.0 (except for its inexactness), and both should behave the same in all numeric contexts. Clearly, in a unified numeric model, if a==b
and c==d
, a/c
should equal b/d
(taking some liberties due to rounding for inexact numbers), and since everybody agrees that 1.0/2.0
equals 0.5, 1/2
should also equal 0.5. Likewise, since 1//2
equals zero, 1.0//2.0
should also equal zero.
Aesthetically, x//y
doesn’t please everyone, and hence several variations have been proposed. They are addressed here:
x div y
. This would introduce a new keyword. Since div
is a popular identifier, this would break a fair amount of existing code, unless the new keyword was only recognized under a future division statement. Since it is expected that the majority of code that needs to be converted is dividing integers, this would greatly increase the need for the future division statement. Even with a future statement, the general sentiment against adding new keywords unless absolutely necessary argues against this.div(x, y)
. This makes the conversion of old code much harder. Replacing x/y
with x//y
or x div y
can be done with a simple query replace; in most cases the programmer can easily verify that a particular module only works with integers so all occurrences of x/y
can be replaced. (The query replace is still needed to weed out slashes occurring in comments or string literals.) Replacing x/y
with div(x, y)
would require a much more intelligent tool, since the extent of the expressions to the left and right of the /
must be analyzed before the placement of the div(
and )
part can be decided.x \ y
. The backslash is already a token, meaning line continuation, and in general it suggests an escape to Unix eyes. In addition (this due to Terry Reedy) this would make things like eval("x\y")
harder to get right.In order to reduce the amount of old code that needs to be converted, several alternative proposals have been put forth. Here is a brief discussion of each proposal (or category of proposals). If you know of an alternative that was discussed on c.l.py that isn’t mentioned here, please mail the second author.
/
keep its classic semantics; introduce //
for true division. This still leaves a broken operator in the language, and invites to use the broken behavior. It also shuts off the road to a unified numeric model a la PEP 228.from __past__ import division
to use classic division semantics in a module. This also retains the classic division as a permanent wart, or at least for a long time (eventually the past division statement could raise an ImportError
).During the transitional phase, we have to support three division operators within the same program: classic division (for /
in modules without a future division statement), true division (for /
in modules with a future division statement), and floor division (for //
). Each operator comes in two flavors: regular, and as an augmented assignment operator (/=
or //=
).
The names associated with these variations are:
__div__(), __floordiv__(), __truediv__(); __idiv__(), __ifloordiv__(), __itruediv__().
PyNumber_Divide(), PyNumber_FloorDivide(), PyNumber_TrueDivide(); PyNumber_InPlaceDivide(), PyNumber_InPlaceFloorDivide(), PyNumber_InPlaceTrueDivide().
BINARY_DIVIDE, BINARY_FLOOR_DIVIDE, BINARY_TRUE_DIVIDE; INPLACE_DIVIDE, INPLACE_FLOOR_DIVIDE, INPLACE_TRUE_DIVIDE.
nb_divide, nb_floor_divide, nb_true_divide, nb_inplace_divide, nb_inplace_floor_divide, nb_inplace_true_divide.
The added PyNumberMethod
slots require an additional flag in tp_flags
; this flag will be named Py_TPFLAGS_HAVE_NEWDIVIDE
and will be included in Py_TPFLAGS_DEFAULT
.
The true and floor division APIs will look for the corresponding slots and call that; when that slot is NULL
, they will raise an exception. There is no fallback to the classic divide slot.
In Python 3.0, the classic division semantics will be removed; the classic division APIs will become synonymous with true division.
Command Line OptionThe -Q
command line option takes a string argument that can take four values: old
, warn
, warnall
, or new
. The default is old
in Python 2.2 but will change to warn
in later 2.x versions. The old
value means the classic division operator acts as described. The warn
value means the classic division operator issues a warning (a DeprecationWarning
using the standard warning framework) when applied to ints or longs. The warnall
value also issues warnings for classic division when applied to floats or complex; this is for use by the fixdiv.py
conversion script mentioned below. The new
value changes the default globally so that the /
operator is always interpreted as true division. The new
option is only intended for use in certain educational environments, where true division is required, but asking the students to include the future division statement in all their code would be a problem.
This option will not be supported in Python 3.0; Python 3.0 will always interpret /
as true division.
(This option was originally proposed as -D
, but that turned out to be an existing option for Jython, hence the Q – mnemonic for Quotient. Other names have been proposed, like -Qclassic
, -Qclassic-warn
, -Qtrue
, or -Qold_division
etc.; these seem more verbose to me without much advantage. After all the term classic division is not used in the language at all (only in the PEP), and the term true division is rarely used in the language – only in __truediv__
.)
Floor division will be implemented in all the Python numeric types, and will have the semantics of:
except that the result type will be the common type into which a and b are coerced before the operation.
Specifically, if a and b are of the same type, a//b
will be of that type too. If the inputs are of different types, they are first coerced to a common type using the same rules used for all other arithmetic operators.
In particular, if a and b are both ints or longs, the result has the same type and value as for classic division on these types (including the case of mixed input types; int//long
and long//int
will both return a long).
For floating point inputs, the result is a float. For example:
For complex numbers, //
raises an exception, since floor()
of a complex number is not allowed.
For user-defined classes and extension types, all semantics are up to the implementation of the class or type.
Semantics of True DivisionTrue division for ints and longs will convert the arguments to float and then apply a float division. That is, even 2/1
will return a float (2.0)
, not an int. For floats and complex, it will be the same as classic division.
The 2.2 implementation of true division acts as if the float type had unbounded range, so that overflow doesn’t occur unless the magnitude of the mathematical result is too large to represent as a float. For example, after x = 1L << 40000
, float(x)
raises OverflowError
(note that this is also new in 2.2: previously the outcome was platform-dependent, most commonly a float infinity). But x/x
returns 1.0 without exception, while x/1
raises OverflowError
.
Note that for int and long arguments, true division may lose information; this is in the nature of true division (as long as rationals are not in the language). Algorithms that consciously use longs should consider using //
, as true division of longs retains no more than 53 bits of precision (on most platforms).
If and when a rational type is added to Python (see PEP 239), true division for ints and longs should probably return a rational. This avoids the problem with true division of ints and longs losing information. But until then, for consistency, float is the only choice for true division.
The Future Division StatementIf from __future__ import division
is present in a module, or if -Qnew
is used, the /
and /=
operators are translated to true division opcodes; otherwise they are translated to classic division (until Python 3.0 comes along, where they are always translated to true division).
The future division statement has no effect on the recognition or translation of //
and //=
.
See PEP 236 for the general rules for future statements.
(It has been proposed to use a longer phrase, like true_division or modern_division. These don’t seem to add much information.)
Open IssuesWe expect that these issues will be resolved over time, as more feedback is received or we gather more experience with the initial implementation.
//
the quotient operator, and the /
operator the ratio operator. I’m not sure about this – for some people quotient is just a synonym for division, and ratio suggests rational numbers, which is wrong. I prefer the terminology to be slightly awkward if that avoids unambiguity. Also, for some folks quotient suggests truncation towards zero, not towards infinity as floor division says explicitly.-Qnew
with another one that requires -Qold
. But I believe that the VPython folks need a way to enable true division by default, and other educators might need the same. These usually have enough control over the library packages available in their environment.__div__()
, __floordiv__()
and __truediv__()
seems painful; and what to do in 3.0? Maybe we only need __div__()
and __floordiv__()
, or maybe at least true division should try __truediv__()
first and __div__()
second.Resolution: For long true division, Python uses an internal float type with native double precision but unbounded range, so that OverflowError doesn’t occur unless the quotient is too large to represent as a native double.
OverflowError
if the long is out of range.
Resolution: This has been implemented, but, as above, the magnitude of the inputs to long true division doesn’t matter; only the magnitude of the quotient matters.
Resolution: Provided the quotient of long true division is representable as a float, it suffers no more than 3 rounding errors: one each for converting the inputs to an internal float type with native double precision but unbounded range, and one more for the division. However, note that if the magnitude of the quotient is too small to represent as a native double, 0.0 is returned without exception (“silent underflow”).
Why isn’t true division called float division?We don’t plan that long ahead, so we can’t say for sure. We want to allow at least two years for the transition. If Python 3.0 comes out sooner, we’ll keep the 2.x line alive for backwards compatibility until at least two years from the release of Python 2.2. In practice, you will be able to continue to use the Python 2.x line for several years after Python 3.0 is released, so you can take your time with the transition. Sites are expected to have both Python 2.x and Python 3.x installed simultaneously.
Why is there a need forBecause I want to keep the door open to
possiblyintroducing rationals and making 1/2 return a rational rather than a float. See
PEP 239.
__truediv__
and __itruediv__
?
How do I write code that works under the classic rules as well as under the new rules without usingWe don’t want to make user-defined classes second-class citizens. Certainly not with the type/class unification going on.
//
or a future division statement?
How do I specify the division semantics forUse
x*1.0/y
for true division,
divmod(x, y)
(
PEP 228) for int division. Especially the latter is best hidden inside a function. You may also write
float(x)/y
for true division if you are sure that you don’t expect complex numbers. If you know your integers are never negative, you can use
int(x/y)
– while the documentation of
int()
says that
int()
can round or truncate depending on the C implementation, we know of no C implementation that doesn’t truncate, and we’re going to change the spec for
int()
to promise truncation. Note that classic division (and floor division) round towards negative infinity, while
int()
rounds towards zero, giving different answers for negative numbers.
input()
, compile()
, execfile()
, eval()
and exec
?
What about code compiled by the codeop module?They inherit the choice from the invoking module.
PEP 236now lists this as a resolved problem, referring to
PEP 264.
Will there be conversion tools or aids?This is dealt with properly; see
PEP 264.
Why is my question not answered here?Certainly. While these are outside the scope of the PEP, I should point out two simple tools that will be released with Python 2.2a3:
Tools/scripts/finddiv.py
finds division operators (slightly smarter thangrep /
) andTools/scripts/fixdiv.py
can produce patches based on run-time analysis.
ImplementationBecause we weren’t aware of it. If it’s been discussed on c.l.py and you believe the answer is of general interest, please notify the second author. (We don’t have the time or inclination to answer every question sent in private email, hence the requirement that it be discussed on c.l.py first.)
Essentially everything mentioned here is implemented in CVS and will be released with Python 2.2a3; most of it was already released with Python 2.2a2.
CopyrightThis document has been placed in the public domain.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4