预计阅读本页时间:-
Division: Classic, Floor, and True
You’ve seen how division works in the previous sections, so you should know that it behaves slightly differently in Python 3.0 and 2.6. In fact, there are actually three flavors of division, and two different division operators, one of which changes in 3.0:
X / Y
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
Classic and true division. In Python 2.6 and earlier, this operator performs classic division, truncating results for integers and keeping remainders for floating-point numbers. In Python 3.0, it performs true division, always keeping remainders regardless of types.
X // Y
Floor division. Added in Python 2.2 and available in both Python 2.6 and 3.0, this operator always truncates fractional remainders down to their floor, regardless of types.
True division was added to address the fact that the results of the original classic division model are dependent on operand types, and so can be difficult to anticipate in a dynamically typed language like Python. Classic division was removed in 3.0 because of this constraint—the / and // operators implement true and floor division in 3.0.
In sum:
- In 3.0, the / now always performs true division, returning a float result that includes any remainder, regardless of operand types. The // performs floor division, which truncates the remainder and returns an integer for integer operands or a float if any operand is a float.
- In 2.6, the / does classic division, performing truncating integer division if both operands are integers and float division (keeping remainders) otherwise. The // does floor division and works as it does in 3.0, performing truncating division for integers and floor division for floats.
Here are the two operators at work in 3.0 and 2.6:
C:\misc> C:\Python30\python
>>>
>>> 10 / 4 # Differs in 3.0: keeps remainder
2.5
>>> 10 // 4 # Same in 3.0: truncates remainder
2
>>> 10 / 4.0 # Same in 3.0: keeps remainder
2.5
>>> 10 // 4.0 # Same in 3.0: truncates to floor
2.0
C:\misc> C:\Python26\python
>>>
>>> 10 / 4
2
>>> 10 // 4
2
>>> 10 / 4.0
2.5
>>> 10 // 4.0
2.0
Notice that the data type of the result for // is still dependent on the operand types in 3.0: if either is a float, the result is a float; otherwise, it is an integer. Although this may seem similar to the type-dependent behavior of / in 2.X that motivated its change in 3.0, the type of the return value is much less critical than differences in the return value itself. Moreover, because // was provided in part as a backward-compatibility tool for programs that rely on truncating integer division (and this is more common than you might expect), it must return integers for integers.
Supporting either Python
Although / behavior differs in 2.6 and 3.0, you can still support both versions in your code. If your programs depend on truncating integer division, use // in both 2.6 and 3.0. If your programs require floating-point results with remainders for integers, use float to guarantee that one operand is a float around a / when run in 2.6:
X = Y // Z # Always truncates, always an int result for ints in 2.6 and 3.0
X = Y / float(Z) # Guarantees float division with remainder in either 2.6 or 3.0
Alternatively, you can enable 3.0 / division in 2.6 with a __future__ import, rather than forcing it with float conversions:
C:\misc> C:\Python26\python
>>> from __future__ import division # Enable 3.0 "/" behavior
>>> 10 / 4
2.5
>>> 10 // 4
2
Floor versus truncation
One subtlety: the // operator is generally referred to as truncating division, but it’s more accurate to refer to it as floor division—it truncates the result down to its floor, which means the closest whole number below the true result. The net effect is to round down, not strictly truncate, and this matters for negatives. You can see the difference for yourself with the Python math module (modules must be imported before you can use their contents; more on this later):
>>> import math
>>> math.floor(2.5)
2
>>> math.floor(-2.5)
-3
>>> math.trunc(2.5)
2
>>> math.trunc(-2.5)
-2
When running division operators, you only really truncate for positive results, since truncation is the same as floor; for negatives, it’s a floor result (really, they are both floor, but floor is the same as truncation for positives). Here’s the case for 3.0:
C:\misc> c:\python30\python
>>> 5 / 2, 5 / −2
(2.5, −2.5)
>>> 5 // 2, 5 // −2 # Truncates to floor: rounds to first lower integer
(2, −3) # 2.5 becomes 2, −2.5 becomes −3
>>> 5 / 2.0, 5 / −2.0
(2.5, −2.5)
>>> 5 // 2.0, 5 // −2.0 # Ditto for floats, though result is float too
(2.0, −3.0)
The 2.6 case is similar, but / results differ again:
C:\misc> c:\python26\python
>>> 5 / 2, 5 / −2 # Differs in 3.0
(2, −3)
>>> 5 // 2, 5 // −2 # This and the rest are the same in 2.6 and 3.0
(2, −3)
>>> 5 / 2.0, 5 / −2.0
(2.5, −2.5)
>>> 5 // 2.0, 5 // −2.0
(2.0, −3.0)
If you really want truncation regardless of sign, you can always run a float division result through math.trunc, regardless of Python version (also see the round built-in for related functionality):
C:\misc> c:\python30\python
>>> import math
>>> 5 / −2 # Keep remainder
−2.5
>>> 5 // −2 # Floor below result
-3
>>> math.trunc(5 / −2) # Truncate instead of floor
−2
C:\misc> c:\python26\python
>>> import math
>>> 5 / float(−2) # Remainder in 2.6
−2.5
>>> 5 / −2, 5 // −2 # Floor in 2.6
(−3, −3)
>>> math.trunc(5 / float(−2)) # Truncate in 2.6
−2
Why does truncation matter?
If you are using 3.0, here is the short story on division operators for reference:
>>> (5 / 2), (5 / 2.0), (5 / −2.0), (5 / −2) # 3.0 true division
(2.5, 2.5, −2.5, −2.5)
>>> (5 // 2), (5 // 2.0), (5 // −2.0), (5 // −2) # 3.0 floor division
(2, 2.0, −3.0, −3)
>>> (9 / 3), (9.0 / 3), (9 // 3), (9 // 3.0) # Both
(3.0, 3.0, 3, 3.0)
For 2.6 readers, division works as follows:
>>> (5 / 2), (5 / 2.0), (5 / −2.0), (5 / −2) # 2.6 classic division
(2, 2.5, −2.5, −3)
>>> (5 // 2), (5 // 2.0), (5 // −2.0), (5 // −2) # 2.6 floor division (same)
(2, 2.0, −3.0, −3)
>>> (9 / 3), (9.0 / 3), (9 // 3), (9 // 3.0) # Both
(3, 3.0, 3, 3.0)
Although results have yet to come in, it’s possible that the nontruncating behavior of / in 3.0 may break a significant number of programs. Perhaps because of a C language legacy, many programmers rely on division truncation for integers and will have to learn to use // in such contexts instead. Watch for a simple prime number while loop example in Chapter 13, and a corresponding exercise at the end of Part IV that illustrates the sort of code that may be impacted by this / change. Also stay tuned for more on the special from command used in this section; it’s discussed further in Chapter 24.