Python 3.7 math.remainder 和 %(模运算符) 之间的区别
Difference between Python 3.7 math.remainder and %(modulo operator)
来自 What’s New In Python 3.7
我们可以看到有新的math.remainder
。它说
Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference x - n*y
, where n is the closest integer to the exact value of the quotient x / y
. If x / y
is exactly halfway between two consecutive integers, the nearest even integer is used for n
. The remainder r = remainder(x, y)
thus always satisfies abs(r) <= 0.5 * abs(y)
.
Special cases follow IEEE 754: in particular, remainder(x, math.inf)
is x for any finite x, and remainder(x, 0)
and remainder(math.inf, x)
raise ValueError
for any non-NaN x. If the result of the remainder operation is zero, that zero will have the same sign as x.
On platforms using IEEE 754 binary floating-point, the result of this operation is always exactly representable: no rounding error is introduced.
但是我们还记得有一个%
符号是
remainder of x / y
我们还看到有一条给操作员的注释:
Not for complex numbers. Instead convert to floats using abs()
if appropriate.
我还没试过 运行 Python 3.7 如果可能的话。
但我试过了
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> 100 % math.inf
100.0
>>> math.inf % 100
nan
>>> 100 % 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
所以区别在于,我们会得到 ValueError
而不是 nan
和 ZeroDivisionError
,正如文档中所说的那样。
所以问题是%
和math.remainder
有什么区别? math.remainder
是否也适用于复数(%
缺少复数)?主要优势是什么?
这是来自官方 CPython github repo 的 source of math.remainder
。
Return the IEEE 754-style remainder of x with respect to y. For finite
x and finite nonzero y, this is the difference x - n*y
, where n is the
closest integer to the exact value of the quotient x / y
. If x / y
is
exactly halfway between two consecutive integers, the nearest even
integer is used for n. The remainder r = remainder(x, y)
thus always
satisfies abs(r) <= 0.5 * abs(y)
.
对于模数,这是 m = x - n*y
,其中 n
是 floor(x/y)
,因此对于余数,0 <= m < y
而不是 abs(r) <= 0.5 * abs(y)
。
所以
modulo(2.7, 1) = 0.7
remainder(2.7, 1) = -0.3
感谢@MaartenFabré,我没有注意细节:
math.remainder()
is the difference x - n*y
, where n
is the closest integer to the exact value of the quotient x / y
我构建了 Python 3.7:
Python 3.7.0a0 (heads/master:f34c685020, May 8 2017, 15:35:30)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
区别如下:
零作为除数:
>>> math.remainder(1, 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> 1 % 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
基本数字,其中math.remainder(x, y) < x % y
>>> math.remainder(5, 3)
-1.0
>>> 5 % 3
2
复数:
>>> math.remainder(3j + 2, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float
>>> (3j + 2) % 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't mod complex numbers.
无穷大(math.inf
)
>>> math.remainder(3, math.inf)
3.0
>>> 3 % math.inf
3.0
>>> math.remainder(math.inf, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> math.inf % 3
nan
来自 What’s New In Python 3.7
我们可以看到有新的math.remainder
。它说
Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference
x - n*y
, where n is the closest integer to the exact value of the quotientx / y
. Ifx / y
is exactly halfway between two consecutive integers, the nearest even integer is used forn
. The remainderr = remainder(x, y)
thus always satisfiesabs(r) <= 0.5 * abs(y)
.Special cases follow IEEE 754: in particular,
remainder(x, math.inf)
is x for any finite x, andremainder(x, 0)
andremainder(math.inf, x)
raiseValueError
for any non-NaN x. If the result of the remainder operation is zero, that zero will have the same sign as x.On platforms using IEEE 754 binary floating-point, the result of this operation is always exactly representable: no rounding error is introduced.
但是我们还记得有一个%
符号是
remainder of
x / y
我们还看到有一条给操作员的注释:
Not for complex numbers. Instead convert to floats using
abs()
if appropriate.
我还没试过 运行 Python 3.7 如果可能的话。
但我试过了
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> 100 % math.inf
100.0
>>> math.inf % 100
nan
>>> 100 % 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
所以区别在于,我们会得到 ValueError
而不是 nan
和 ZeroDivisionError
,正如文档中所说的那样。
所以问题是%
和math.remainder
有什么区别? math.remainder
是否也适用于复数(%
缺少复数)?主要优势是什么?
这是来自官方 CPython github repo 的 source of math.remainder
。
Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference
x - n*y
, where n is the closest integer to the exact value of the quotientx / y
. Ifx / y
is exactly halfway between two consecutive integers, the nearest even integer is used for n. The remainderr = remainder(x, y)
thus always satisfiesabs(r) <= 0.5 * abs(y)
.
对于模数,这是 m = x - n*y
,其中 n
是 floor(x/y)
,因此对于余数,0 <= m < y
而不是 abs(r) <= 0.5 * abs(y)
。
所以
modulo(2.7, 1) = 0.7
remainder(2.7, 1) = -0.3
感谢@MaartenFabré,我没有注意细节:
math.remainder()
is the differencex - n*y
, wheren
is the closest integer to the exact value of the quotientx / y
我构建了 Python 3.7:
Python 3.7.0a0 (heads/master:f34c685020, May 8 2017, 15:35:30)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
区别如下:
零作为除数:
>>> math.remainder(1, 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> 1 % 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
基本数字,其中math.remainder(x, y) < x % y
>>> math.remainder(5, 3)
-1.0
>>> 5 % 3
2
复数:
>>> math.remainder(3j + 2, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float
>>> (3j + 2) % 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't mod complex numbers.
无穷大(math.inf
)
>>> math.remainder(3, math.inf)
3.0
>>> 3 % math.inf
3.0
>>> math.remainder(math.inf, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> math.inf % 3
nan