【问题标题】:Python remainder operatorPython 余数运算符
【发布时间】:2013-08-28 22:40:22
【问题描述】:

Python中有余数运算符吗?我不要求取模运算符,而是要求余数。例如:

-5 mod 2 = 1

但是

-5 rem 2 = -1 # where "rem" is a remainder operator.

我必须自己实现吗;)?

【问题讨论】:

  • 是的,你必须自己实现。
  • @katrielalex 但编程很难:(
  • 你真的只想要一个截断除法余数,而不需要截断除法吗?
  • "我不要求取模运算符,而是求余数。"你明白那些是同样的事情吗?请参阅 Wikipedia:“在计算中,模(有时称为模)运算会找到一个数字除以另一个数字的余数。” (或者你只是想要关于底片的不同规则?)

标签: python


【解决方案1】:

“模”或“余数”实际上有三种不同的定义,而不是两种:

  • 截断除法余数:符号与被除数相同。
  • Floored 除法余数:符号与除数相同。
  • 欧几里得除法余数:符号始终为正。

称其中一个为“模数”而另一个为“余数”非常令人困惑;这三个对于这两个术语都是有用的定义。

几乎每一种语言都只提供三种中的一种(Fortran 是一个明显的例外)。* 大多数语言都提供与该语言的除法运算符匹配的一种。** 因为 Python 使用底除法(遵循 Knuth 在 The Art 中的论点的计算机编程),它使用匹配的余数运算符。

如果你想要其中任何一个,你必须手动编写它。这不是很难; this Wikipedia article 展示了如何实现这三个。

例如:

def trunc_divmod(a, b):
    q = a / b
    q = -int(-q) if q<0 else int(q)
    r = a - b * q
    return q, r

现在,以您为例:

>>> q, r = trunc_divmod(-5, 2)
>>> print(q, r)
-2 -1

* 通常同时提供调用的语言会在mod 上截断余数,并在rem 上留下一些变体……但这绝对不是可以依赖的。例如,Fortran 调用底余数modulo,而Scheme 调用欧几里德余数mod。

** 两个值得注意的例外是 C90 和 C++03,这将选择权留给实现。虽然许多实现使用截断除法和余数,但有些不使用(有些甚至使用截断除法和取余数,这意味着 a = b * (a/b) + a%b 甚至不起作用……)。

【讨论】:

    【解决方案2】:

    编辑:当您要求进行余数运算时,您的意思并不完全清楚,执行此操作的方法将取决于对输出符号的要求。

    如果标志总是积极的 divmod 可以做你想做的事,它在标准库中

    http://docs.python.org/2/library/functions.html#divmod

    您可能还想查看内置的二进制算术运算符:

    http://docs.python.org/2/reference/expressions.html

    如果余数必须与传递的参数具有相同的符号,那么您必须自己滚动,例如:

    import math
    def rem(x,y):
        res = x % y
        return math.copysign(res,x)
    

    【讨论】:

    • 不,divmod(a, b) 返回的内容与(a/b, a%b) 完全相同。换句话说,OP 仍然会得到1,而不是他想要的-1。
    • 显然“如果标志总是积极的”没有帮助,因为 OP 给我们的唯一示例 -5 rem 2 = -1 并非如此。
    • 新版本彻底坏了——用rem(-5, -2)试试吧。
    【解决方案3】:

    math.fmod 是否符合您的要求?

    【讨论】:

    • 不,fmod 返回结果“由平台 C 库定义”。这意味着哪种类型的余数取决于实现。 (C99确实定义了一个,但至少 Python 2.7 是用 C90 编写的,而不是 C99。)所以,这个可能在他的平台上做他正在寻找的事情......然后做在另一个平台上有所不同。 (还有一个事实是fmod 将所有内容都转换为float,并且文档明确表示在使用整数时它不是首选。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多