Difference between Python 3.7 math.remainder and %(modulo operator)

送分小仙女□ 提交于 2020-08-07 05:02:16

问题


From What’s New In Python 3.7 we can see that there is new math.remainder. It says

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.

But we also remember that there is % symbol which is

remainder of x / y

We also see that there is a note to operator:

Not for complex numbers. Instead convert to floats using abs() if appropriate.

I haven't tried to run Python 3.7 if it's even possible.

But i tried

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

So difference would be, instead of nan and ZeroDivisionError we would get ValueError as it says in docs.

So the question is what is the difference between % and math.remainder? Would math.remainder also work with complex numbers(% lacks from it)? What is the main advantage?

Here is the source of math.remainder from official CPython github repo.


回答1:


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).

for the modulo this is m = x - n*y where n is the floor(x/y), so 0 <= m < y instead of abs(r) <= 0.5 * abs(y) for the remainder.

so

modulo(2.7, 1) = 0.7
remainder(2.7, 1) = -0.3



回答2:


Thanks to @MaartenFabré, I wasn't being attentive to details:

math.remainder() is the difference x - n*y, where n is the closest integer to the exact value of the quotient x / y

I built 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

And here are differences:

Zero as divisor:

>>> 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

Basic numbers, where math.remainder(x, y) < x % y

>>> math.remainder(5, 3)
-1.0
>>> 5 % 3
2

Complex numbers:

>>> 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.

Infinity(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


来源:https://stackoverflow.com/questions/43845375/difference-between-python-3-7-math-remainder-and-modulo-operator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!