【问题标题】:Modulo for negative dividends in PythonPython中负股息的模
【发布时间】:2012-04-21 06:08:12
【问题描述】:

一直在查看其他答案,但我仍然不明白 python 中负数的模

例如df的回答

x == (x/y)*y + (x%y)

所以 (-2)%5 = -2 - (-2/5)*5 = 3 是有道理的

这不是 (-2 - (-2/5)*5) =0 还是我疯了? Modulus operation with negatives values - weird thing?

与此相同 negative numbers modulo in python 他从哪里得到-2?

最后,如果符号依赖于红利,为什么负红利的输出不与正红利相同?

例如

的输出
print([8%5,-8%5,4%5,-4%5])

[3, 2, 4, 1]

【问题讨论】:

  • 您可以使用math.fmod 获得与在 C 或 Java 中相同的行为。

标签: python modulo


【解决方案1】:

说 -a % b 需要计算。例如。 r= 11 % 10 找到 11 之后的下一个可以被 10 整除的数字,即在 11 之后除以下一个数字得到余数 0。

在上述情况下,它的 20 除以 10 得到 0。 因此,20-11 = 9 是需要添加到 11 的数字。

如果 60 个弹珠需要平分给 8 个人的概念,实际上除以 60/8 后得到的是 7.5,因为你不能将弹珠减半,60 之后的下一个可以被 8 完全整除的值是 64 . 因此,需要再添加 4 个弹珠,以便每个人都能分享弹珠的乐趣。

这就是 Python 在使用模运算符除负数时的做法。

【讨论】:

    【解决方案2】:

    在 Python 中,a // b 被定义为 floor(a/b),而其他大多数语言中整数除法被定义为 trunc(a/b)。 a % b = a - (a // b) * b的解释有相应的区别。

    原因是 Python 对 % 运算符(和 divmod)的定义通常比其他语言更有用。例如:

    def time_of_day(seconds_since_epoch):
        minutes, seconds = divmod(seconds_since_epoch, 60)
        hours, minutes = divmod(minutes, 60)
        days, hours = divmod(hours, 24)
        return '%02d:%02d:%02d' % (hours, minutes, seconds)
    

    使用此函数,time_of_day(12345) 返回 '03:25:45',正如您所期望的那样。

    但是在纪元之前 12345 秒是什么时候?使用 Python 对 divmod 的定义,time_of_day(-12345) 正确返回 '20:34:15'

    如果我们重新定义divmod 以使用/% 的C 定义会怎样?

    def divmod(a, b):
        q = int(a / b)   # I'm using 3.x
        r = a - b * q
        return (q, r)
    

    现在,time_of_day(-12345) 返回'-3:-25:-45',这不是一天中的有效时间。如果标准 Python divmod 函数以这种方式实现,则您必须编写特殊情况代码来处理负输入。但是对于地板式的划分,就像我的第一个例子一样,它就行了。

    【讨论】:

    • 我只使用了一点 Python,并没有给它留下深刻的印象,但看到至少有一种编程语言支持可用的除法运算符,我感到很温暖。您的时间示例很棒。我看到有人抱怨说欧几里得模数运算符不能从负数中提取数字(例如,-123 % 10 即使最后一个数字是 3,也会产生 7)。另一方面,产生 -3 的 C 风格余数运算符并没有更好。
    【解决方案3】:

    查看this BetterExplained article 并查看@David 的评论(第6 条)以了解其他人在谈论什么。

    由于我们使用整数工作,所以我们进行 int 除法,在 Python 中,floors 答案相对于 C。有关此内容的更多信息,请阅读 Guido's article

    至于你的问题:

    >>> 8 % 5  #B'coz (5*1) + *3* = 8
    3
    >>> -8 % 5 #B'coz (5*-2) + *2* = -8
    2
    

    希望对您有所帮助。一开始它也让我很困惑(现在仍然如此)! :)

    【讨论】:

      【解决方案4】:

      当您除以整数 (-2/5)*5 时,not 的计算结果为 -2,就像在您习惯的代数中一样。尝试将其分解为两个步骤,首先评估括号中的部分。

      1. (-2/5) * 5 = (-1) * 5
      2. (-1) * 5 = -5

      第 1 步的原因是您正在执行 int 除法,在 python 2.x 中,它返回相当于浮点除法结果的四舍五入到最接近的整数。

      在 python 3 及更高版本中,2/5 将返回一个浮点数,请参阅PEP 238

      【讨论】:

        【解决方案5】:

        这背后的基本原理实际上是least residue 的数学定义。 Python 尊重这个定义,而在大多数其他编程语言中,模运算符实际上更像是“除法后的提醒”运算符。要计算-5 % 11 的最小余数,只需将 11 与 -5 相加,直到在[0,10] 范围内得到一个正整数,结果为 6。

        【讨论】:

          【解决方案6】:

          在 Python 中,取模是根据两个规则计算的:

          • (a // b) * b + (a % b) == a,和
          • a % bb 具有相同的符号。

          将此与整数除法向下舍入(朝向 -∞)这一事实结合起来,并解释了结果行为。

          如果你做-8 // 5,你得到-1.6向下取整,即-2。将其乘以 5 得到 -10; 2 是您必须添加到该数字才能得到 -8 的数字。因此,-8 % 5 为 2。

          【讨论】:

            猜你喜欢
            • 2023-03-28
            • 2017-06-23
            • 2017-01-11
            • 2021-02-25
            • 2021-03-20
            • 2011-04-22
            • 1970-01-01
            相关资源
            最近更新 更多