【问题标题】:Difference between Python 3.7 math.remainder and %(modulo operator)Python 3.7 math.remainder 和 %(模运算符) 之间的区别
【发布时间】:2017-05-08 10:30:37
【问题描述】:

来自What’s New In Python 3.7 我们可以看到有新的math.remainder。它说

返回 x 相对于 y 的 IEEE 754 样式余数。对于有限 x 和有限非零 y,这是 x - n*y 的差值,其中 n 是与商 x / y 的精确值最接近的整数。如果x / y 恰好在两个连续整数之间,则最接近的偶数将用于n。因此,余数 r = remainder(x, y) 始终满足 abs(r) <= 0.5 * abs(y)

特殊情况遵循 IEEE 754:特别是,remainder(x, math.inf) 是 x 对于任何有限 x,remainder(x, 0)remainder(math.inf, x) raise ValueError 对于任何非 NaN x。如果余数运算的结果为零,则该零的符号与 x 相同。

在使用 IEEE 754 二进制浮点的平台上,此操作的结果始终可以精确表示:不会引入舍入误差。

但我们也记得有 % 符号是

x / y的其余部分

我们也看到了给运营商的一个注解:

不适用于复数。如果合适,请使用abs() 转换为浮点数。

如果可能的话,我还没有尝试过运行 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 而不是 nanZeroDivisionError,正如它在文档中所说的那样。

那么问题是%math.remainder 有什么区别? math.remainder 是否也适用于复数(% 缺少它)?主要优势是什么?

这是来自官方 CPython github 存储库的 source of math.remainder

【问题讨论】:

    标签: python math cpython python-3.7


    【解决方案1】:

    返回 x 相对于 y 的 IEEE 754 样式余数。对于有限 x 和有限非零 y,这是x - n*y 的差异,其中 n 是 与商x / y 的精确值最接近的整数。如果x / y 是 正好在两个连续整数的中间,最接近的偶数 整数用于 n。其余的 r = remainder(x, y) 因此总是 满足abs(r) &lt;= 0.5 * abs(y).

    对于模,这是m = x - n*y,其中nfloor(x/y),所以余数是0 &lt;= m &lt; y 而不是abs(r) &lt;= 0.5 * abs(y)

    所以

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

    【讨论】:

    • 其实是-0.3 for remainder(2.7, 1)
    【解决方案2】:

    感谢@MaartenFabré,我没有注意细节:

    math.remainder() 是差 x - n*y,其中 n 是最接近商 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) &lt; 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-24
      • 2016-05-18
      • 2011-10-22
      • 2012-10-06
      • 2010-12-30
      • 2019-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多