Worked in most of the comments on the newsgroup on the previous draft.

Even changed the title.
This commit is contained in:
Guido van Rossum 2001-07-27 18:07:12 +00:00
parent c79f778838
commit 1edc94b63d
1 changed files with 93 additions and 31 deletions

View File

@ -1,23 +1,23 @@
PEP: 238
Title: Non-integer Division
Title: Changing the Division Operator
Version: $Revision$
Author: pep@zadka.site.co.il (Moshe Zadka), guido@python.org (Guido van Rossum)
Status: Draft
Type: Standards Track
Created: 11-Mar-2001
Python-Version: 2.2
Post-History: 16-Mar-2001, 26-Jul-2001
Post-History: 16-Mar-2001, 26-Jul-2001, 27-Jul-2001
Abstract
The current division (/) operator has an ambiguous meaning for
numerical arguments: it returns the floor of the mathematical
result if the arguments are ints or longs, but it returns a
reasonable approximation of the 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.
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
@ -123,7 +123,7 @@ Motivation
Variations
Esthetically, x//y doesn't please everyone, and hence several
Aesthetically, x//y doesn't please everyone, and hence several
variations have been proposed: x div y, or div(x, y), sometimes in
combination with x mod y or mod(x, y) as an alternative spelling
for x%y.
@ -148,7 +148,7 @@ Variations
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 analized before the
the left and right of the / must be analyzed before the
placement of the "div(" and ")" part can be decided.
@ -161,17 +161,16 @@ Alternatives
c.l.py that isn't mentioned here, please mail the second author.
- Let / keep its classic semantics; introduce // for true
division. This doesn't solve the problem that the classic /
operator makes it hard to write polymorphic numeric functions
accept int and float arguments, and still requires the use of
x*1.0/y whenever true divisions is required.
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[0].
- Let int division return a special "portmanteau" type that
behaves as an integer in integer context, but like a float in a
float context. The problem with this is that after a few
operations, the int and the float value could be miles apart,
it's unclear which value should be used in comparisons, and of
course many contexts (e.g. conversion to string) don't have a
course many contexts (like conversion to string) don't have a
clear integer or float context.
- Use a directive to use specific division semantics in a module,
@ -188,10 +187,10 @@ Alternatives
- Use a directive (or some other way) to specify the Python
version for which a specific piece of code was developed. This
requires future Python interpreters to be able to emulate
*exactly* every previous version of Python, and moreover to do
so for multiple versions in the same interpreter. This is way
too much work. A much simpler solution is to keep multiple
interpreters installed.
*exactly* several previous versions of Python, and moreover to
do so for multiple versions within the same interpreter. This
is way too much work. A much simpler solution is to keep
multiple interpreters installed.
Specification
@ -240,6 +239,9 @@ Specification
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 Option
@ -248,10 +250,10 @@ Command Line Option
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 DeprecatinWarning using the standard warning framework)
when applied to ints or longs. 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
warning (a DeprecationWarning using the standard warning
framework) when applied to ints or longs. 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.
@ -259,6 +261,13 @@ Command Line Option
This option will not be supported in Python 3.0; Python 3.0 will
always interpret / as true division.
(Other names have been proposed, like -Dclassic, -Dclassic-warn,
-Dtrue, or -Dold_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__.)
Semantics of Floor Division
@ -267,16 +276,47 @@ Semantics of Floor Division
a // b == floor(a/b)
except that the type of a//b will be the type a and b will be
coerced into. Specifically, if a and b are of the same type, a//b
will be of that type too.
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:
3.5//2.0 == 1.0
For complex numbers, // raises an exception, since float() 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 Division
True 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.
return a float (2.0), not an int. For floats and complex, it will
be the same as classic division.
Note that for 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 //.
If and when a rational type is added to Python (see PEP 239[2]),
true division for ints and longs should probably return a
rational. This avoids the problem with true division of longs
losing information. But until then, for consistency, float is the
only choice for true division.
The Future Division Statement
@ -292,13 +332,19 @@ The Future Division Statement
See PEP 236[4] 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 Issues
- It has been proposed to call // the quotient operator. I like
this. I might rewrite the PEP to use this if enough people like
it. (But isn't the assumption that this truncates towards
zero?)
- It has been proposed to call // 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.
- It has been argued that a command line option to change the
default is evil. It can certainly be dangerous in the wrong
@ -312,13 +358,25 @@ Open Issues
FAQ
Q. Why isn't true division called float division?
A. Because I want to keep the door open to *possibly* introducing
rationals and making 1/2 return a rational rather than a
float. See PEP 239[2].
Q. Why is there a need for __truediv__ and __itruediv__?
A. We don't want to make user-defined classes second-class
citizens. Certainly not with the type/class unification going
on.
Q. How do I write code that works under the classic rules as well
as under the new rules without using // or a future division
statement?
A. Use x*1.0/y for true division, divmod(x, y)[0] for int
division. Especially the latter is best hidden inside a
function. You may also write floor(x)/y for true division if
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
@ -343,6 +401,10 @@ FAQ
includes a future division statement, but that's not a general
solution.
Q. Will there be conversion tools or aids?
A. Certainly, but these are outside the scope of the PEP.
Q. Why is my question not answered here?
A. Because we weren't aware of it. If it's been discussed on